+ 2

How do you create thread-safe Singleton in Java?

Please give your answer with an example

21st May 2019, 7:57 PM
Athman Hassan
Athman Hassan - avatar
13 Réponses
+ 3
You just need to synchronize the get method that returns your reference: https://code.sololearn.com/cnIa16ff0Efw/?ref=app
21st May 2019, 8:29 PM
Paul
+ 2
Thanks guys have been following your comments and i really appreciate your answers and all the explanations.
23rd May 2019, 4:40 AM
Athman Hassan
Athman Hassan - avatar
+ 1
Paul has a good implementation except that we shouldn't use the same object/class to synchronize over. We should have a private monitor that does that.
22nd May 2019, 1:11 AM
Chriptus13
Chriptus13 - avatar
+ 1
By pure curiosity Chriptus13, why wouldn't you use the same object for synchronization ?
22nd May 2019, 1:58 AM
Paul
+ 1
Paul I posted that as a comment on your code 😄
22nd May 2019, 8:09 AM
Chriptus13
Chriptus13 - avatar
+ 1
Chriptus13 I see your point and agree that it would be safer. However, the added safety is limited since the point of making the Singleton thread safe was to not have to deal with synchronization when handling it thus it's unlikely you need/want to synchronize on it. Also, if you want to use a monitor object, you can increase the speed by reducing the synchronized block (see FasterSingleton in the code).
22nd May 2019, 9:33 AM
Paul
+ 1
Paul actually that has problems because you are reading shared state outside the synchronized block. You could instead use AtomicReferences to prevent and optimize it.
22nd May 2019, 5:05 PM
Chriptus13
Chriptus13 - avatar
+ 1
Paul reference assignment is indeed atomic altrough thats not the only thing you are doing, you cannot forget the if check before that assignment. And since JVM doesn't garantee any instruction ordenation on multi thread code you cannot assume that no other thread can execute that assignment before the current one even though both had seen the if check true.
22nd May 2019, 11:42 PM
Chriptus13
Chriptus13 - avatar
+ 1
Chriptus13 I invite to look at the code again. What you mention would only happen if there was no null check before the assignment. Even if two threads see _inst as a null reference with the first if, one will get the lock first on _mon and do the single instantiation then free _mon. Then the second thread will lock _mon and do nothing since _inst is not null anymore then release the lock. No double instantiation, everything is fine.
23rd May 2019, 12:02 AM
Paul
+ 1
Paul oh I see, I'm sorry I must have made confusion!! Anyways it is not safe to split the reads/writes of shared state between synchronized and non synchronized blocks. But also now I spot that you forget to remove the synchronized modifier on the method signature.
23rd May 2019, 12:14 AM
Chriptus13
Chriptus13 - avatar
+ 1
Chriptus13 oh thanks for the synchronized on the function. For the read data outside a synchronized block, it depends on what you are trying to achieve this code is completely thread-safe (since the assignment is atomic) and will be a lot faster than the one where the synchronization is happening at every call. I would agree that this would a bit too extreme for someone who is starting to learn java. But for someone a bit experienced who will understand what is happening and need a bit more speed, the second implementation is definitely the way to go. Moreover, most of the time when doing multi-threading, it is a good thing to reduce the size of the synchronized code.
23rd May 2019, 12:27 AM
Paul
- 1
Chriptus13 AtomicReference only adds protection for the update of the reference (which is already protected by _mon) The reference assignment is already atomic which means when I check for null outside the synchronized, it's either null or a valid reference (ref https://stackoverflow.com/questions/44283378/why-is-reference-assignment-atomic-in-java#44287276) Thus, there is no data race possible when checking the equality with null and thus the code is fine
22nd May 2019, 6:02 PM
Paul