简体   繁体   English

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

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

It's very well known among Java programmers that in order for double-checked locking to function correctly, the variable must be declared volatile , and synchronizing the initialization of the object is not enough. 在Java程序员中众所周知,为了使双重检查锁定正常运行,必须将变量声明为volatile ,并且同步对象的初始化是不够的。

The awareness is probably mostly because the semantics of the volatile keyword were changed in 1.5 to include a "happens before" relationship, at least in part to make double-checked locking safe; 意识可能主要是因为volatile关键字的语义在1.5中被改变为包括“之前发生”关系,至少部分是为了使双重检查锁定安全; from what I understand, the "happens-before" relationship means writing to a volatile variable causes all cached variables in the thread to be written to main memory, and after reading from a volatile variable, all cached variables are considered stale, and must be re-read from main memory, so that everything written before a write to a volatile variable is guaranteed to "happen before" a later read from that variable. 根据我的理解,“发生在之前”关系意味着写入volatile变量会导致线程中的所有缓存变量被写入主内存,并且在从volatile变量读取后,所有缓存变量都被认为是陈旧的,并且必须是从主内存重新读取,以便在写入volatile变量之前写入的所有内容都保证在“稍后从该变量读取之前”发生。

Stack Overflow seems to believe that, for C#, volatile is unnecessary for double-checked locking (despite noting concerns that this may be specific to certain CPUs or to Microsoft's implementation), while also believing that the semantics of Java's synchronized statement are exactly the same as C#'s lock statement, which suggests that the same issues identified in Java would also exist for C#, unless some other major difference exists in the semantics of double-checked locking between the two languages. Stack Overflow 似乎相信 ,对于C#, volatile是双重检查锁定所必需的(尽管有人担心这可能是特定于某些CPU或Microsoft的实现),同时也认为Java的synchronized语句的语义完全相同作为C#的lock语句,这表明在C#中也存在Java中发现的相同问题,除非在两种语言之间的双重检查锁定的语义中存在一些其他主要差异。

So...which is correct? 那么......哪个是正确的? Is double-checked locking in C# actually less dangerous than in Java? C#中的双重检查锁定实际上比Java更危险吗? If so, what language semantics differ to make that the case? 如果是这样,那么语言语义有何不同呢?

If not, what specifically can go wrong without volatile ? 如果没有,没有volatile具体可能出现什么问题? Does the semantics of volatile in C# establish a "happens-before" relationship like Java, so that double-checked locking is as safe in C# with volatile as it is in Java since 1.5? C#中volatile的语义是否像Java一样建立了“发生在之前”的关系,因此双重检查锁定在C#中是安全的,因为它是1.5以来在Java中的volatile

From MSDN : "The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times." 来自MSDN :“volatile关键字表示某个字段可能被同时执行的多个线程修改。声明为volatile的字段不受编译器优化的影响,这些优化假定由单个线程访问。这可确保最大化到目前为止,该字段中存在最新值。“

So, volatile is only useful if you are changing the variable's value from multiple threads. 因此,volatile仅在您从多个线程更改变量值时才有用。 If you lock() the code areas which acess shared resources with same locking object you are guaranteed that only one thread can access those code areas simultaneously, then volatile is not needed unless you are modifying the locking object (which is a really bad idea). 如果你锁定()使用相同锁定对象共享资源的代码区域,保证只有一个线程可以同时访问这些代码区域,那么除非你修改锁定对象,否则不需要volatile(这是一个非常糟糕的主意) 。

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

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