繁体   English   中英

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

[英]Is `volatile` required for double-checked locking in Java but not C#?

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

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

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

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

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

来自MSDN :“volatile关键字表示某个字段可能被同时执行的多个线程修改。声明为volatile的字段不受编译器优化的影响,这些优化假定由单个线程访问。这可确保最大化到目前为止,该字段中存在最新值。“

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM