假设我有一个非易失性的int字段,以及一个它Interlocked.Increment
的线程.另一个线程可以直接安全地读取它,还是读取也需要互锁?
我以前认为我必须使用互锁读取来保证我看到当前值,因为毕竟,该字段不是易失性的.我一直在Interlocked.CompareExchange(int, 0, 0)
努力实现这一目标.
但是,我偶然发现了这个答案,这表明实际的普通读取总会看到Interlocked.Increment
ed值的当前版本,并且因为int读取已经是原子的,所以不需要做任何特殊的事情.我还发现了Microsoft拒绝Interlocked.Read(ref int)请求的请求,进一步表明这完全是多余的.
那么我能真正安全地阅读这样一个int
领域的最新价值Interlocked
吗?
以下代码
using System.Threading;
class Test
{
volatile int counter = 0;
public void Increment()
{
Interlocked.Increment(ref counter);
}
}
Run Code Online (Sandbox Code Playgroud)
引发以下编译器警告:
"A reference to a volatile field will not be treated as volatile"
Run Code Online (Sandbox Code Playgroud)
我在这里做错了什么来提出这个警告?为什么编译器会对此发出警告?
在 C# 中处理延迟初始化对象的线程安全方法是什么?假设我有以下Lazy
构造:
Lazy<MyClass> lazy = new Lazy<MyClass>(() => MyClass.Create(), true);
Run Code Online (Sandbox Code Playgroud)
稍后,我可能想处置MyClass
创建的实例。大多数现有的解决方案都推荐这样的内容:
if (lazy.IsValueCreated)
{
lazy.Value.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
但据我所知,IsValueCreated
没有任何锁:https://referencesource.microsoft.com/#mscorlib/system/Lazy.cs,284
MyClass
这意味着当我们检查 时,另一个线程可能正在初始化过程中IsValueCreated
。在这种情况下,我们将观察IsValueCreated
到错误,并最终泄漏资源。这里正确的做法是什么?还是我错过了一些微妙的细节?