如果我有一个非常不可变的类型(所有成员都是只读的,如果它们是引用类型成员,那么它们也指的是不可变的对象).
private ReadOnlyCollection<SomeImmutableType> m_PropName = null; public ReadOnlyCollection<SomeImmutableType> PropName { get { if(null == m_PropName) { ReadOnlyCollection<SomeImmutableType> temp = /* do lazy init */; m_PropName = temp; } return m_PropName; } }
从我能说的:
m_PropName = temp;
…是线程安全的我不担心两个线程同时进行初始化,因为它将是罕见的,两个结果将从逻辑角度来看是一样的,如果我没有,我宁愿不使用锁至.
这会工作吗优缺点都有什么?
编辑:
感谢您的答案.我可能会使用锁向前移动.然而,我很惊讶,没有人提出编译器意识到temp变量是不必要的,只是直接分配给m_PropName的可能性.如果是这样,那么读取线程可能会读取一个尚未完成构造的对象.编译器是否防止这种情况?
(答案似乎表明运行时不会允许这种情况发生.)
编辑:
所以我决定用this article by Joe Duffy的启发式联锁CompareExchange方法.
基本上:
private ReadOnlyCollection<SomeImmutableType> m_PropName = null; public ReadOnlyCollection<SomeImmutableType> PropName { get { if(null == m_PropName) { ReadOnlyCollection<SomeImmutableType> temp = /* do lazy init */; System.Threading.Interlocked(ref m_PropName,temp,null); } return m_PropName; } }
这应该是确保在此对象实例上调用此方法的所有线程将获得对同一对象的引用,因此==运算符将工作.有可能浪费工作,这是很好的 – 它只是使这是一个乐观的算法.
如下面的一些评论中所指出的,这取决于.NET 2.0内存模型的工作原理.否则,m_PropName应声明为volatile.
解决方法
原文地址:https://www.jb51.cc/csharp/97456.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。