在Java中进行双重检查锁定是否需要`volatile`而不是C#?

时间:2014-04-15 00:01:15

标签: c# java volatile double-checked-locking

在Java程序员中众所周知,为了使双重检查锁定正常运行,必须将变量声明为volatile,并且同步对象的初始化是不够的。

意识可能主要是因为volatile关键字的语义在1.5中被更改为包括“之前发生”关系,至少部分是为了使双重检查锁定安全;根据我的理解,“发生在之前”关系意味着写入volatile变量会导致线程中的所有缓存变量被写入主内存,并且在从volatile变量读取后,所有缓存变量都被认为是陈旧的,并且必须是从主内存重新读取,以便在写入volatile变量之前写入的所有内容都保证在“稍后从该变量读取之前”发生。

Stack Overflow seems to believe,对于C#,volatile对于双重检查锁定是不必要的(尽管有人担心这可能是特定于某些CPU或Microsoft的实现),同时也认为Java的synchronized语句的语义是exactly the same作为C#的lock语句,这表明在Java中也存在相同的问题,除非在双语义中存在一些其他主要区别。 - 检查两种语言之间的锁定。

所以......哪个是正确的? C#中的双重检查锁定实际上比Java更危险吗?如果是这样,那么语言语义有何不同呢?

如果没有,没有volatile会出现什么问题? C#中volatile的语义是否像Java一样建立了“发生在之前”的关系,因此双重检查锁定在C#中与volatile一样安全,因为它在Java中是1.5?

1 个答案:

答案 0 :(得分:2)

From MSDN:" volatile关键字表示某个字段可能被同时执行的多个线程修改。声明为volatile的字段不受编译器优化的约束,这些优化假定由单个线程进行访问。这样可确保始终在字段中显示最新值。"

因此,volatile只在您从多个线程更改变量的值时才有用。如果你锁定()使用相同锁定对象共享资源的代码区域,保证只有一个线程可以同时访问这些代码区域,那么除非你修改锁定对象,否则不需要volatile(这是一个非常糟糕的主意)