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.
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; 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.
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.
So...which is correct? Is double-checked locking in C# actually less dangerous than in Java? If so, what language semantics differ to make that the case?
If not, what specifically can go wrong without 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?