在Java中,双重检查锁定需要使用“volatile”关键字吗?而在C#中却不需要?

5
在Java程序员中,众所周知,为了使双重检查锁定正常工作,变量必须声明为volatile,并且同步对象的初始化是不够的。这种意识可能主要是因为volatile关键字的语义在1.5中被改变以包括“发生在”关系,至少部分上是为了使双重检查锁定安全;据我所知,“发生在”关系意味着写入volatile变量会导致线程中所有缓存变量被写入主内存,并且在从volatile变量读取后,所有缓存变量都被认为是过时的,必须从主内存重新读取,以便在写入volatile变量之前写入的所有内容都保证在稍后从该变量读取之前“发生”。

Stack Overflow 似乎认为,对于C#,volatile在双重检查锁定中是不必要的(尽管注意到这可能特定于某些CPU或Microsoft的实现),同时也认为Java的synchronized语句的语义与C#的lock语句完全相同,这表明在Java中发现的相同问题也将存在于C#中,除非两种语言之间的双重检查锁定的语义存在其他主要差异。

那么...哪一个是正确的?C#中的双重检查锁定是否比Java更安全?如果是,有什么语言语义的差异使得情况如此?

如果不是,没有volatile会出现什么具体问题?C#中volatile的语义是否建立了类似Java的“先行发生”关系,因此使用volatile的C#中的双重检查锁定与Java 1.5之后一样安全?


请查看此链接此链接 - mellamokb
1个回答

3

来自MSDN的解释:volatile关键字表示一个字段可能会被多个同时执行的线程修改。声明为volatile的字段不会受到编译器优化,这些优化假定只有单个线程访问该字段。这确保了该字段中始终存在最新的值。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接