这个双重检查的锁是否需要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语句。我还认为,在这种情况下,双重检查锁定是不合适的/不会提供任何性能提升,而普通锁定就可以了。
我希望有人能证实或否认这些想法。
如果Connect((方法也使用lock (syncRoot)
,那么代码应该在没有volatile的情况下工作。
但你在这里看不到dcl的任何好处,为什么要经历麻烦/风险?
我对volatile的理解是,你会想要它。我相信volatile会强制每次读取值,并阻止编译器缓存值或执行其他优化,从而导致无法从内存中读取"正确"值。
请参阅Eric Lippert的回答,他在回答中提到了易失性阅读的使用。
您是正确的,volatile
关键字读取的是内存,而不是CPU缓存。但这并不意味着它是线程安全的。将syncLock变量更改为静态修饰符,以确保这在多个实例中是线程安全的。这是推荐的方法。