This week's book giveaway is in the Cloud/Virtualization forum.
We're giving away four copies of Building Blockchain Apps and have Michael Yuan on-line!
See this thread for details.
Win a copy of Building Blockchain Apps this week in the Cloud/Virtualization forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Liutauras Vilda
  • Knute Snortum
  • Bear Bibeault
Sheriffs:
  • Devaka Cooray
  • Jeanne Boyarsky
  • Junilu Lacar
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
  • salvin francis
Bartenders:
  • Tim Holloway
  • Piet Souris
  • Frits Walraven

Design patterns - Singletons and double checked locking

 
Ranch Hand
Posts: 92
2
IntelliJ IDE Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The Head First design patterns book mentions the following about the Singleton design pattern.

3. Use “double-checked locking” to reduce the use of synchronization in getInstance().With double-checked locking, we first check to see if an instance is created, and if not, THEN we synchronize. This way, we only synchronize the first time through, just what we want.





Why do we check if uniqueInstance is null again in the synchronized block ?
 
Marshal
Posts: 68115
258
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Many people think that Singleton is an anti‑pattern.
Beware of double checked locking. It used not to work at all well. There is a better way to create a single instance:-...but that is no longer the “correct” way to create a singleton. This is:-I am told that the new Java® memory model (new? it was introduced in Java5) allows double checked locking to work. But both the other ways to create a singleton are better. See Effective Java by Joshua Bloch. I don't have my copy to hand to heck the page number.
 
Campbell Ritchie
Marshal
Posts: 68115
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tom Joe wrote:. . . Why do we check if uniqueInstance is null again in the synchronized block ?

To guard against another th‍read having called the getInstance() method after the first == null test and before entering the synchronized block. If that happens, then two distinct instances will be created.
 
Marshal
Posts: 25215
65
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I am told that the new Java® memory model (new? it was introduced in Java5) allows double checked locking to work.



Yes, it was Java 5. Which was released in 2004. I was thinking wow, it's years ago that I last heard about this double-checked locking business. But like they say, old code never dies.
 
Campbell Ritchie
Marshal
Posts: 68115
258
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Paul Clapham wrote:. . . Java 5. Which was released in 2004.

And I can remember using the “new” features of Java5.

. . . old code never dies.

But maybe it should be put out of its misery
 
Tom Joe
Ranch Hand
Posts: 92
2
IntelliJ IDE Eclipse IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:

Tom Joe wrote:. . . Why do we check if uniqueInstance is null again in the synchronized block ?

To guard against another th‍read having called the getInstance() method after the first == null test and before entering the synchronized block. If that happens, then two distinct instances will be created.



Isn't a synchronized block supposed to allow only one thread at a time ? So, I don't understand why two threads would be able to get into the synchronized block.

 
Paul Clapham
Marshal
Posts: 25215
65
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Tom Joe wrote:Isn't a synchronized block supposed to allow only one thread at a time ? So, I don't understand why two threads would be able to get into the synchronized block.



It's kind of hard to discuss that without having the version without double-checked locking to look at. I suppose you have that version in the book you're looking at? Then it would help if you posted it.
 
Saloon Keeper
Posts: 11488
247
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Two threads don't get inside the synchronized block. But then, the first null check isn't inside a synchronized block...
 
Rancher
Posts: 4493
47
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thread A gets to line 7, and instance is null, so moves onto line 8.
Control might then go to thread B (before the synching) who gets to line 7, so instance is still null.
You now have two threads at line 8, both of which would create a copy of the singleton if there wasn't a further null check.
 
Rancher
Posts: 3439
35
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Singletons and double-checked locking are never very good "Beginning Java" topics, in my opinion.  This might be a better topic for Java in General.

Note that double-checked locking is still useful, not for actual singletons, but for lazy loading of instance fields.  From the Book of Joshua, 3rd Edition, p. 334:


Interestingly, Bloch himself got this wrong in early printings; be sure to check the errata.  The version I posted above is the correct one, not the original.

Also, double-checked locking implementations work since Java 5, provided they declare the double-checked field as volatile.  Which this implementation does, as does the version the original poster asked about.  But if they forget the volatile, it's not safe.

Lastly, a nice thread-safe version of this code has already been made as part of Guava's Suppliers.memoize() method.  So you can just use it, quite easily:

 
Saloon Keeper
Posts: 2514
118
Google Web Toolkit Eclipse IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For reference only, there's a version that I am aware of :
Boom !! Lazy loaded. No need to to synchronize. No thread based issues. Nothing !
Having said that, I'd still not prefer to see this code in production. It's more like a party trick at this point of time.
 
Mike Simmons
Rancher
Posts: 3439
35
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, the static holder class is a perfectly respectable way to achieve lazy loading for a static field.  It could also be used to make a lazy-loaded singleton, though it's a little more vulnerable to someone creating extra instances through reflection, unless you guard against it.  So for a singleton they usually recommend the enum approach as it's a little simpler and more secure.  I think it was discovered just before enums came into the language, and once we had enums, there was no longer much need for the static holder version.  But there's nothing wrong with it.

Going back to Suppliers.memoize(), it's nice to note that for a static lazy-loaded field, the only change is to add the word static in two places.  It's otherwise the same.  So, bonus points for simplicity and consistency:


 
Paul Clapham
Marshal
Posts: 25215
65
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
And in real life, most singletons can be eagerly loaded. The vast majority, in fact. The only exception (that I can think of) is if the class containing the singleton has methods which don't involve the singleton, and the singleton is expensive to set up and might not end up being used. I'd submit that designs like that are extremely rare and can usually be modified so that eager loading makes sense.

If you do that, then all of those synchronization issues go away. So all of those discussions back in the old days about double-checked locking and so on were all in the aid of a scenario which almost never occurs. But that was rarely mentioned in the discussions, so probably there's a whole lot of instances of the double-checked locking code out there in working code which were unnecessary.
 
salvin francis
Saloon Keeper
Posts: 2514
118
Google Web Toolkit Eclipse IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I looked the OP's question and I feel that it needs more discussion...
Particularly this code:
I don't recall where I read this.. but here goes..
Imagine 100 calls to your getInstance() method trying to get an instance of your object. Your code should try to only prevent call #2 from not creating a new object. The rest 98 calls will get the same instance since the if (uniqueInstance == null)  condition will start failing for all of them. Now imagine Call#1 and Call#2 are two different threads both trying to execute at the same time. Both will get the value as null and both will proceed to the next statement.

Now, synchronized is blocking call. It ensures that all threads reaching at that point of time wait, and only one enters it. We want it to be the exceptional case and not the normal case. Hence, only one thread enters the block and creates a new object once and then exits. Now, when the next waiting thread enters it, it finds the object to be not null and exits. This takes care of the corner 2% of the cases and the rest 98% of the calls simply do not enter this block. A synchronized block should only cover the critical section of the code that you absolutely want a single thread to execute. It can also wreck havoc with deadlocks that are very difficult to debug. Hence, placing guard conditions around it makes sense in this case.

You can similarly deduce for a scenario where the first #3 calls are three different threads running getInstance() at the same instant in time. But I hope this explanation clears your original question.
 
Greenhorn
Posts: 23
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
According to Jeanne and Scott book, the first checking is not to lock unnecessarily if the instance exists. The second checking tries to confirm again if the instance have not got created by another thread the moment before acquiring the lock.
 
You can't have everything. Where would you put it?
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!