这个双重检查锁需要的volatile关键字是否有效?

时间:2011-07-12 20:04:02

标签: c# multithreading

  

可能重复:
  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,因为如果它第一次读取不正确的值,那么它会认为它实际上已断开连接并且不会进入锁定语句。我也认为在这种情况下,双重检查锁定是不合适的/不会提供任何性能增益,只是一个普通的锁定就可以完成这项工作。

我希望有人确认或否认这些想法。

3 个答案:

答案 0 :(得分:1)

这是我对易变的理解,是的,你会想要它。我相信volatile会强制每次都读取该值,并且会阻止编译器缓存该值或执行一些其他优化,这些优化会导致不能从内存中读取“正确”值。

请参阅Eric Lippert's answer,他提到使用易失性读数。

答案 1 :(得分:1)

如果Connect()方法也使用lock (syncRoot),则代码应该在没有volatile的情况下工作。

但是你不会在这里看到dcl的任何好处,为什么要经历麻烦/风险呢?

答案 2 :(得分:-2)

你是对的,volatile关键字从内存读取而不是CPU缓存。但这并不意味着它是线程安全的。将syncLock变量更改为静态修饰符,以确保跨多个实例的线程安全。这是推荐的方法。