Java中的双重检查锁定是否需要“volatile”,而不是C#?

Java中的双重检查锁定是否需要“volatile”,而不是C#?,c#,java,volatile,double-checked-locking,C#,Java,Volatile,Double Checked Locking,Java程序员非常清楚,为了使双重检查锁定正常工作,必须声明变量volatile,并且同步对象的初始化是不够的 意识到这一点可能主要是因为volatile关键字的语义在1.5中被更改为包含“之前发生”关系,至少部分是为了使双重检查锁定安全;据我所知,“之前发生”关系意味着写入易失性变量会导致线程中的所有缓存变量写入主存,并且在读取易失性变量后,所有缓存变量都被视为过时,必须从主存重新读取,因此,在写入易失性变量之前写入的所有内容都保证在以后从该变量读取之前“发生” 堆栈溢出,对于C#,volat

Java程序员非常清楚,为了使双重检查锁定正常工作,必须声明变量
volatile
,并且同步对象的初始化是不够的

意识到这一点可能主要是因为
volatile
关键字的语义在1.5中被更改为包含“之前发生”关系,至少部分是为了使双重检查锁定安全;据我所知,“之前发生”关系意味着写入易失性变量会导致线程中的所有缓存变量写入主存,并且在读取易失性变量后,所有缓存变量都被视为过时,必须从主存重新读取,因此,在写入易失性变量之前写入的所有内容都保证在以后从该变量读取之前“发生”

堆栈溢出,对于C#,
volatile
不需要双重检查锁定(尽管注意到这可能是特定于某些CPU或Microsoft的实现),同时也相信Java的
synchronized
语句的语义与C#
lock
语句相同,这表明Java中发现的相同问题也会存在于C#中,除非两种语言之间的双重检查锁定语义存在其他一些主要差异

那么…哪一个是正确的?C#中的双重检查锁定实际上比Java中的危险性小吗?如果是这样的话,有什么不同的语言语义来说明这一点

如果不是,没有
volatile
,具体会出什么问题?C中的
volatile
语义是否建立了一种类似Java的“之前发生”关系,从而使双重检查锁定在C中与
volatile
一样安全,就像自1.5以来在Java中一样?

来自:volatile关键字表示一个字段可能被同时执行的多个线程修改。声明为volatile的字段不受假定由单个线程访问的编译器优化的约束。这可确保字段中始终存在最新的值。”

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

请参阅和。