可能重复:
The need for volatile modifier in double checked locking in .NET
鉴于以下代码片段可以同时由多个线程执行,是否需要使用volatile关键字来确保始终从内存中读取connected
的“实际值”,而不是缓存?
(假设Disconnect()
只会被调用一次(即如果它第一次不能正常工作并且connected
的值被读为false,则不会再次尝试) )。
public class MyClass
{
private readonly object syncRoot = new object();
private bool connected;
public void Disconnect()
{
if (connected)
{
lock (syncRoot)
{
if (connected)
{
// log off here
// ...
connected = false;
}
}
}
}
public void Connect()
{
lock (syncRoot)
{
// blah
// blah
connected = true;
}
}
}
我的感觉是,如果使用双重检查锁定,那么它确实需要标记为volatile,因为如果它第一次读取不正确的值,那么它会认为它实际上已断开连接并且不会进入锁定语句。我也认为在这种情况下,双重检查锁定是不合适的/不会提供任何性能增益,只是一个普通的锁定就可以完成这项工作。
我希望有人确认或否认这些想法。
答案 0 :(得分:1)
这是我对易变的理解,是的,你会想要它。我相信volatile会强制每次都读取该值,并且会阻止编译器缓存该值或执行一些其他优化,这些优化会导致不能从内存中读取“正确”值。
请参阅Eric Lippert's answer,他提到使用易失性读数。
答案 1 :(得分:1)
如果Connect()方法也使用lock (syncRoot)
,则代码应该在没有volatile的情况下工作。
但是你不会在这里看到dcl的任何好处,为什么要经历麻烦/风险呢?
答案 2 :(得分:-2)
你是对的,volatile
关键字从内存读取而不是CPU缓存。但这并不意味着它是线程安全的。将syncLock变量更改为静态修饰符,以确保跨多个实例的线程安全。这是推荐的方法。