这个双重检查的锁是否需要volatile关键字才能工作

本文关键字:volatile 关键字 工作 是否 检查 | 更新日期: 2023-09-27 18:02:06

可能重复:
在双重检查锁定中需要volatile修饰符。净

给定以下代码片段,它可以同时由多个线程执行,是否需要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,因为如果它第一次读取不正确的值,那么它会认为它实际上已经断开连接,不会进入lock语句。我还认为,在这种情况下,双重检查锁定是不合适的/不会提供任何性能提升,而普通锁定就可以了。

我希望有人能证实或否认这些想法。

这个双重检查的锁是否需要volatile关键字才能工作

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

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

我对volatile的理解是,你会想要它。我相信volatile会强制每次读取值,并阻止编译器缓存值或执行其他优化,从而导致无法从内存中读取"正确"值。

请参阅Eric Lippert的回答,他在回答中提到了易失性阅读的使用。

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