views:

1311

answers:

4

I came across this article discussing why the double-check locking paradigm is broken in java. Is the paradigm valid for .net (in particular, C#), if variables are declared volatile?

+2  A: 

Implementing the Singleton Pattern in C# talks about this problem in the third version.

It says:

Making the instance variable volatile can make it work, as would explicit memory barrier calls, although in the latter case even experts can't agree exactly which barriers are required. I tend to try to avoid situations where experts don't agree what's right and what's wrong!

The author seems to imply that double locking is less likely to work than other strategies and thus should not be used.

Cameron MacFarland
+1  A: 

Note than in Java (and most likely in .Net as well), double-checked locking for singleton initialization is completely unnecessary as well as broken. Since classes are not initialized until they're first used, the desired lazy initialization is already achieved by this;

private static Singleton instance = new Singleton();

Unless your Singleton class contains stuff like constants that may be accessed before a Singleton instance is first used, this is all you need to do.

Michael Borgwardt
DCL does work since Java 5 (see Jon Skeet's comment, though he didn't talk about exactly what you must do to make it work). You need: 1. Java 5. 2. DCL reference declared volatile (or atomic in some way, e.g., using AtomicReference).
Chris Jester-Young
See the "Under the new Java Memory Model" section in http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Chris Jester-Young
For java Singleton and DCL patterns see this link http://blogs.sun.com/cwebster/entry/double_check_locking
facildelembrar
+9  A: 

Double-checking locking now works in Java as well as C# (the Java memory model changed and this is one of the effects). However, you have to get it exactly right. If you mess things up even slightly, you may well end up losing the thread safety.

As other answers have stated, if you're implementing the singleton pattern there are much better ways to do it. Personally, if I'm in a situation where I have to choose between double-checked locking and "lock every time" code I'd go for locking every time until I'd got real evidence that it was causing a bottleneck. When it comes to threading, a simple and obviously-correct pattern is worth a lot.

Jon Skeet
@Jon: Article from the question states that `volatile` helps for JDK5+. What about .NET? Was `volatile` enough to implement a proper double-check locking on .NET 1.1? (for example, what about the example "Third version - attempted thread-safety using double-check locking" in your article: is it technically 'fixed' when `volatile` put on `instance` static field?)
IgorK
@IgorK: Yes, I *believe* it works when the variable is marked as volatile.
Jon Skeet
@Jon: OK, thank you. At least for singletons we have better solutions indeed.
IgorK
A: 

.NET 4.0 has a new type: Lazy<T> that takes away any concern about getting the pattern wrong. It's part of the new Task Parallel Library.

See the MSDN Parallel Computing Dev Center: http://msdn.microsoft.com/en-us/concurrency/default.aspx

BTW, there's a backport (I believe it is unsupported) for .NET 3.5 SP1 available here.

David Messner