is google volley singleton really thread safe? - java

In the android tranning Use a Singleton Pattern
public static synchronized MySingleton getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
I'm thinking it still not thread safey.
If Object A do getInstance and Object B do getInstance synchronously,it will still break the lock, and create two mInstance.
Because synchronized for method is only available for ONE object from different thread, but not for 2 objects.
So DO I have wrong comprehension, or below code is more safe than original?
public static synchronized MySingleton getInstance(Context context) {
synchronized(MySingleton.class)
{
if (mInstance == null) {
mInstance = new MySingleton(context);
}
}
return mInstance;
}

Your two examples do exactly the same thing.
This:
class Foobar {
static synchronized mumble(...) { doSomething(); }
}
Is just a shorthand way to write:
class Foobar {
static mumble(...) {
synchronized(Foobar.class) { doSomething(); }
}
}
A similar rule applies for non-static methods. This:
class Foobar {
synchronized mumble(...) { doSomething(); }
}
is just a shorthand way to write:
class Foobar {
mumble(...) {
synchronized(this) { doSomething(); }
}
}
I'm not sure I really understand your question, but maybe you do have "wrong comprehension".
I don't like the shortcut forms because synchronized methods draw attention away from the fact that methods are not what we want to protect with synchronization. What we want to protect is data.
We use synchronization when it is impossible for one thread to update some collection of data without creating a temporary, invalid state that other threads must not be allowed to see. We wrap a synchronized block around the code that creates the invalid state, and we also wrap synchronized blocks that synchronize on the same object around every piece of code that must not be allowed to see the invalid state.
The JVM will never allow two threads to be synchronized on the same object at the same time, so if we've done everything right, no thread will be allowed to see the invalid state except for the one that temporarily creates it.

Related

Why this synchronisation is not working in given scenario?

package singleton;
public class SingletonClass {
private static SingletonClass singleton = null;
private SingletonClass() {
}
static boolean stopThread = true;
//approach 1 which fails in multithereaded env
/*public static SingletonClass getInstance(){
if(null == singleton){
try {
if(stopThread){
stopThread = false;
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
singleton = new SingletonClass();
}
return singleton;
}*/
//approach 2 which works
//method is synchronized
/* public static synchronized SingletonClass getInstance(){
if(null == singleton){
try {
if(stopThread){
stopThread = false;
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
singleton = new SingletonClass();
}
return singleton;
}*/
***//approach 3 which is failing but I don't understand why
//big block of code is synchronized
public static SingletonClass getInstance(){
if(null == singleton){
synchronized (SingletonClass.class){
try {
if(stopThread){
stopThread = false;
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
singleton = new SingletonClass();
}
}
return singleton;
}***
//small block of code is synchronized, checked null again because even object instantiation is synchronised
//if we don't check null, it will create new object once again
//approach 4 which works
/* public static SingletonClass getInstance(){
if(null == singleton){
try {
if(stopThread){
System.out.println("in thread...");
stopThread = false;
//even if we interchange above 2 lines it makes whole lot of difference
//till the time it takes to print "in thread"
//2nd thread reaches there n enters if(stopThread) block because
//stopThread is still true because 1st thread spent time in writing that sentence and
//did not set stopThread = false by the time 2nd thread reached there
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (SingletonClass.class){
System.out.println("in this block");
if(null == singleton){
singleton = new SingletonClass();
}
}
}
return singleton;
}*/
}
---------------------------------------------------------
package singleton;
public class ThreadUsage implements Runnable {
#Override
public void run() {
SingletonClass singletonOne = SingletonClass.getInstance();
System.out.println(singletonOne.hashCode());
}
}
----------------------------------------------------------------
package singleton;
class ThreadUsageTest {
public static void main(String[] args) {
Runnable runnableOne = new ThreadUsage();
Runnable runnableTwo = new ThreadUsage();
new Thread(runnableOne).start();
new Thread(runnableTwo).start();
}
}
---------------------------------------------------------------------------
In approach 3, it's not giving same hashCode for 2 objects, I've kept both Thread.sleep as well as object instantiation under synchronised block so what I'm thinking is , 2nd thread should not even enter this block until 1st finishes, but it's still doing and creating 2nd object leading to diff hashCode. What am I mssing here? Could someone correct my understanding here ? If I check for null b4 object creation then it's working as expected but why would I need to check null again here because my entire code is under synchronised block?
if(null == singleton)
singleton = new SingletonClass();
Here's one way that code (approach 3) ends up creating and returning two (or more) separate objects for the singleton:
Thread A enters the function and sees null for singleton
Thread B enters the function and sees null for singleton
Thread A enters the synchronized block
Thread B waits because it can't enter the synchronized block
Thread A assigns to singleton
Thread A exits the synchronized block
Thread A returns one object
Thread B enters the synchronized block
Thread B assigns to singleton
Thread B returns a different object
E.g., there's a gap between the null check and entering the synchronized block that follows it.
To solve it, just make getInstance a synchronized method and remove the synchronized block inside it:
public static synchronized SingletonClass getInstance() {
if (instance == null) {
singleton = new SingletonClass();
}
return singleton;
}
Or if you really want to avoid synchronization on subsequent calls, on Java 5 or later (which hopefully you're using!), declare singleton volatile and check again within the synchronized block:
private static volatile SingletonClass singleton;
// ...
public static SingletonClass getInstance() { // Only works reliably on Java 5 (aka 1.5) and later!
SingletonClass instance = singleton;
if (instance == null) {
synchronized (SingletonClass.class) {
instance = singleton;
if (instance == null) {
singleton = instance = new SingletonClass();
}
}
}
return instance;
}
That's the double-checked locking idiom. In Java 4 (aka 1.4) and earlier that wasn't necessarily reliable, but it is now (provided you use volatile on the member).
In a comment user2683814 asked a good question:
Could you explain the assignment to local variable before null check in the second code snippet ? Checking the class variable directly won’t work ?
Yes, it would work, but less efficiently.
In cases where singleton is non-null, using a local means the method only accesses singleton once. If the code didn't use a local, it would access singleton at least twice (once to check it, once to return it). Since accessing a volatile variable is slightly expensive, better to use the local (which in the code above can be optimized into a register).
That may seem like premature micro-optimization, but if you weren't doing this in performance-critical code, you'd just make the method synchronized and avoid the complexity of double-checked locking entirely. :-)
In approach three, you do a check on the singleton variable; you do this outside of any synchronized block, which is why it doesn't work: There is no guarantee here that threads wait before checking. They all check as fast as they can, which is why 2+ threads may all see a null here, even as one of them is already at work making that instance.
You then synchronize, sure. However, that doesn't magically give this code 'only assign singleton once' powers - after all, the code in that singleton block IS going to assign a newly created instance of SingletonClass to the singleton variable.
Two relevant notes:
[1] The java memory model states that any given field is like schroedinger's cat: Each thread has a copy of it, or doesn't - up to the threading model. An individual copy is sent out to each other thread's copy, or to some of them, at arbitrary times, and the same goes for receiving updates from the others. You can't rely on this mechanism, it may not even be used, there is no way to control it (other than volatile which can help but it's a bit tricky to use correctly). The point is to write your code such that it can't matter. Once you establish 'comes before' / 'comes after' relationships between code, for example because you use a synchronized block, this arbitrary nature goes away, and you are guaranteed visibility (so if code A comes before code B, e.g. because they both synchronize on the same object and A 'won' the battle, anything A writes anywhere will be visible to B once B gets to run, guaranteed, because there is a CA/CB relationship here).
Put that null check inside and all of a sudden the problem goes away.
[2] If all you're trying to accomplish is that there is exactly one instance of SingletonClass, you're barking up the wrong tree. This is not how to do that. It is in fact TRIVIALLY simple. All you do, is this one line:
public class SingletonClass {
public static final SingletonClass instance = new SingletonClass();
private SingletonClass() {
// ensure nobody but you can call this.
}
}
That's it. You may think this means the class is initialized as your app boots, but that's not true. Classes are only loaded if some code is run that uses the class. Assuming ALL uses of SingletonClass involve getting that singleton instance (usually true), this is as good as anything. If for some bizarre reason code may interact with SC without grabbing the singleton, you can still use this mechanism, just, using an inner class:
public class SingletonClass {
private SingletonClass() {}
public static SingletonClass getInstance() {
return Inner.instance;
}
private static class Instance {
private static final SingletonClass instance = new SingletonClass();
}
}
This guaranteed does not call that constructor until someone calls getInstance(), only calls it once, CANNOT ever call it twice, and does it in the most efficient way possible.
EDIT: Formatting.
So problem was both threads can reach method at once and so both will get object as null at once before first one entering synchrosied block.
Using #rzwitserloot and #T.J. Crowder comments, I reached to conclusion that, it's not necessary to use synchronised for creating SIngleton object.
Below code can do that and it's been testing with thread tests n junits as well
package singleton;
public class SingletonClassSecond {
private static SingletonClassSecond singleton = new SingletonClassSecond();
private SingletonClassSecond() {
}
public static SingletonClassSecond getInstance(){
return singleton;
}
}
---------------------------------------------------------------------------
package singleton;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class SingletonClassTest {
#Test
public void shouldCreateSingleton(){
SingletonClass singletonOne = SingletonClass.getInstance();
SingletonClass singletonTwo = SingletonClass.getInstance();
singletonOne.print("1");
singletonTwo.print("2");
Assertions.assertEquals(singletonOne.hashCode(),singletonTwo.hashCode());
}
}
--------------------------------------------------------------------------------
package singleton;
class ThreadUsageTest {
public static void main(String[] args) {
Runnable runnable = new ThreadUsageSecond();
Runnable runnableTwo = new ThreadUsageSecond();
Runnable runnableThree = new ThreadUsageSecond();
Runnable runnableFour = new ThreadUsageSecond();
new Thread(runnable).start();
new Thread(runnableTwo).start();
new Thread(runnableThree).start();
new Thread(runnableFour).start();
}
}
Hashcode is same for all 4 threads.

How to conditionally disable a synchronized block in Java?

Can I do something like that:
synchronized(isSynchronized ? myLock : null) {
}
I want to disable/enable synchronization through a flag. Is it possible?
You could use a lock (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html) and lock it manually.
if (shouldSync) {
lock.lock();
}
try {
// do your stuff
} finally {
if (shouldSync) {
lock.unlock();
}
}
The parameter passed into the synchronized block is not a statement but rather a object to synchronize upon (the mutex). To disable synchronization for whatever reason you should encase the statement in a if-condition as such:
if(condition){
synchronized(myLock){
// Critical segment
}
}
note however, if the evaluation of condition can be dependent on several threads (i.e. multiple writes to a boolean from different threads) you may need to use an existing thread-safe mechanism like AtomicBoolean as such:
AtomicBoolean condition = ... // defined elsewhere
if(condition.get()){
synchronized(myLock){
// Critical segment
}
}
if you need conditional synchronization upon a synchronized method, remove the synchronized keyword from the method declaration and move it into the body:
public synchronized void foo(){
// Critical segment
}
to
public void foo(){
if(condition){
synchronized(this){
// Critical segment
}
}
}
You can't synchronize of null. So if you have another mutex, then definately you could do something like:
synchronized(isSynchronized ? myLock : myLock2) {
}
else you could check and enter the critical section like:
if (isSynchronized) {
synchronized(myLock) {..}
}
Sure. Use an if before hand. Also, make sure the variable isSynchronized is marked volatile.
if (isSynchronized) {
synchronized(myLock) {
// ...
}
}
of course, that won't be synchronized when isSynchronized is false. And that doesn't sound like a great idea, if it's thread-safe it shouldn't be synchronized. If it isn't thread safe, it should be synchronized.
How about this for starters:
if (isSynchronized) {
synchronized(lock) { return doStuff(...); }
} else {
return doStuff(...);
}
private MyType doStuff(...) {
...
}

Singleton with a Listener versus Join

I inherited this code from a previous developer (lol). I'm considering changing this to support a join instead of using a listener kind of callback.
My requirements:
1. I need to have the calling thread wait until the DoMath class thread has completed.
2. I need to prevent other threads from calling it.
This, in another thread (and class) - :
DoMath.getInstance().performMathCalc();
It doesn't wait or sleep of course when it calls this:
public class DoMath {
protected math calc() {
}
public static DoMath getInstance() {
if(_instance == null) {
_instance = new DoMath();
}
return _instance;
}
// perform a synchronous math calc, and return a boolean indicating success or failure.
public boolean performMathCalc() {
MathEngine.setApplicationMode(MathEngine.AUTO);
MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
return true;
}
// perform an async math calc, and call back the listener when done
public void performMathCalc(final listener client) {
Thread mathThread = new Thread(new Runnable() {
public void run() {
boolean result = performMathCalc();
client.mathFinished(result);
}
});
mathThread.setDaemon(true);
mathThread.start();
}
public static interface listener {
public void mathFinished(boolean success);
}
protected static DoMath _instance;
}
So, is it better to just use the listener or implement a join in the calling class?
Do note that this:
public static DoMath getInstance() {
if(_instance == null) {
_instance = new DoMath();
}
return _instance;
}
is not thread-safe. To ensure that your class really is a Singleton (relative to its ClassLoader) you must either synchronize that method or initialize the _instance member in its declaration. Either way, _instance must be private or final or both.
As for your actual requirements,
(1) it seems you want to either change an asynchronous call into a synchronous one, or to put a synchronous wrapper around it. You can do the latter via the existing listener interface, which would preserve the ability to perform asynchronous jobs. If you don't want that then instead of joining, skip launching a new thread at all: just run the computation in the current thread.
(2) How you might prevent multiple threads from running calculations at the same time depends in part on how you address issue (1). If you make everything synchronous then you can just make DoMath.performMathCalc() a synchronized method. If you retain the asynchronous computation option then you could look to package java.util.concurrent.locks for classes that can help you.
Do you really want to pause your thread until the other one as finished? You should never, ever block the main thread.
The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,
t.join();
causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.
(from java docs)
Also, does performMatchCalc() needs to be public ?
Now, at first glance that code actually looks correct, but, you can still prevent someone from starting another calculation. Perhaps with something similar of this :
public class DoMath {
private Thread mathThread;
protected math calc() {
}
public static DoMath getInstance() {
if(_instance == null) {
_instance = new DoMath();
}
return _instance;
}
// perform a synchronous math calc, and return a boolean indicating success or failure.
public boolean performMathCalc() {
if(null != mathThread && mathThread.isAlive())
return false;
MathEngine.setApplicationMode(MathEngine.AUTO);
MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
return true;
}
// perform an async math calc, and call back the listener when done
public void performMathCalc(final listener client) {
//re-start calculation? if so
if(null != mathThread && mathThread.isAlive()) {
matchThread.interrupt();
matchThread = null;
}
mathThread = new Thread(new Runnable() {
public void run() {
boolean result = performMathCalc();
client.mathFinished(result);
}
});
mathThread.setDaemon(true);
mathThread.start();
}
public static interface listener {
public void mathFinished(boolean success);
}
protected static DoMath _instance;
}
I need to have the calling thread wait until the DoMath class thread has completed.
You already have this. Note how there are two performMathCalc methods:
The first method takes no arguments and performs the calculation on the caller thread, then returns the result. This fulfills your first requirement.
The second method is an asynchronous wrapper for the first; it allows the caller to kick off a calculation, then go off an do something else with the understanding that, at some point in the future, someone will be notified that the operation has completed. This is useful functionality, so I would keep it.
I do see one issue with the asynchronous wrapper, however: the listener will not be notified in the event that the core performMathCalc() method throws an exception. Consider using a try/catch/finally block to ensure the listener always gets notified, even if an error occurs. You'll need to decide whether to add a second callback to your listener (e.g., mathFailed) or to simply call mathFinished(false) on errors.
I need to prevent other threads from calling it.
We can accomplish this easily enough, and since the asynchronous version simply delegates to the synchronous version, we only need to lock down the synchronous version. The simplest way would be to mark the method as synchronized, since your class only provides one logical function:
public synchronized boolean performMathCalc() {
MathEngine.setApplicationMode(MathEngine.AUTO);
MathEngine.getInstance().StartMathCalc(MathEngine.DIVISION);
return true;
}
Alternatively, if you end up extending your DoMath class to perform other kinds of operations that are not mutually exclusive, you can synchronize on operation-specific locks.
That leaves us with your singleton accessor:
public static DoMath getInstance() {
if (_instance == null) {
_instance = new DoMath();
}
return _instance;
}
This conditional initialization is not thread-safe. Your singleton is very simple and doesn't have any up-front initialization costs, so simply mark _instance as final static and initialize it in the declaration.

Is it necessary to make this variable volatile?

I was going through an "JAX London 2011" presentation on "Modern Java Concurrency". Between the time duration 43:20 - 43:40, a person from the audience says the shutdown variable in the code below should have been declared as volatile and the presenters agree with it (and say that it was pointed out earlier as well, but they just didnt get to modify the presentation). The code in question is:
public abstract class QueueReaderTask implements Runnable {
private boolean shutdown = false;
protected BlockingQueue<WorkUnit<String>> lbq;
public void run() {
while (!shutdown) {
try {
WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
if (wu != null) { doAction(wu.getWork()); }
} catch (InterruptedException e) {
shutdown = true;
}
}
}
public abstract void doAction(String msg);
public void setQueue(BlockingQueue<WorkUnit<String>> q) { lbq = q; }
}
My Question:
I dont think that shutdown should be declared volatile.
My reasoning is that shutdown being a member of a Runnable, each task/thread will have a distinct private copy of that variable. So, why make it volatile?
But since this was discussed in JAX 2011, I am assuming there were lots of expert Java developers in that audience. I dont think all of them would have missed this !
So, what am I missing ?
P.S:-
I can understand that a variable should be declared volatile if it was (potentially) shared by multiple threads, as in the Double-Checked-Locking pattern :
class Foo {
private volatile Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null)
helper = new Helper();
}
}
return helper;
}
}
each task/thread will have a distinct private copy of that variable. So, why make it 'volatile' ?
You are correct if the shutdown boolean is only modified from within the QueueReaderTask instance. In that case shutdown is only being modified by the one thread and doesn't need to be volatile.
Frankly, the code looks strange to me. Why catch InterruptedException, set the shutdown boolean, and then loop around and exit. Why now just do the following? Why have the shutdown flag at all?
while (true) {
try {
WorkUnit<String> wu = lbq.poll(10, TimeUnit.MILLISECONDS);
if (wu != null) { doAction(wu.getWork()); }
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
}
}
Maybe there is extra code that was removed in the post? If not, I wonder if this was copy and pasted from a larger section of code where shutdown was set to true also in a method call.
P.S:- I can understand that a variable should be declared 'volatile' if it was (potentially) shared by multiple threads, as in the Double-Checked-Locking pattern :
Right. A typical pattern is that shutdown is modified from another thread which is telling the thread to stop processing. In that case it needs to be volatile.

Factory of singleton objects: is this code thread-safe?

I have a common interface for a number of singleton implementations. Interface defines initialization method which can throw checked exception.
I need a factory which will return cached singleton implementations on demand, and wonder if following approach is thread-safe?
UPDATE1: Please don't suggest any 3rd partly libraries, as this will require to obtain legal clearance due to possible licensing issues :-)
UPDATE2: this code will likely to be used in EJB environment, so it's preferrable not to spawn additional threads or use stuff like that.
interface Singleton
{
void init() throws SingletonException;
}
public class SingletonFactory
{
private static ConcurrentMap<String, AtomicReference<? extends Singleton>> CACHE =
new ConcurrentHashMap<String, AtomicReference<? extends Singleton>>();
public static <T extends Singleton> T getSingletonInstance(Class<T> clazz)
throws SingletonException
{
String key = clazz.getName();
if (CACHE.containsKey(key))
{
return readEventually(key);
}
AtomicReference<T> ref = new AtomicReference<T>(null);
if (CACHE.putIfAbsent(key, ref) == null)
{
try
{
T instance = clazz.newInstance();
instance.init();
ref.set(instance); // ----- (1) -----
return instance;
}
catch (Exception e)
{
throw new SingletonException(e);
}
}
return readEventually(key);
}
#SuppressWarnings("unchecked")
private static <T extends Singleton> T readEventually(String key)
{
T instance = null;
AtomicReference<T> ref = (AtomicReference<T>) CACHE.get(key);
do
{
instance = ref.get(); // ----- (2) -----
}
while (instance == null);
return instance;
}
}
I'm not entirely sure about lines (1) and (2). I know that referenced object is declared as volatile field in AtomicReference, and hence changes made at line (1) should become immediately visible at line (2) - but still have some doubts...
Other than that - I think use of ConcurrentHashMap addresses atomicity of putting new key into a cache.
Do you guys see any concerns with this approach? Thanks!
P.S.: I know about static holder class idiom - and I don't use it due to ExceptionInInitializerError (which any exception thrown during singleton instantiation is wrapped into) and subsequent NoClassDefFoundError which are not something I want to catch. Instead, I'd like to leverage the advantage of dedicated checked exception by catching it and handling it gracefully rather than parse the stack trace of EIIR or NCDFE.
You have gone to a lot of work to avoid synchronization, and I assume the reason for doing this is for performance concerns. Have you tested to see if this actually improves performance vs a synchronized solution?
The reason I ask is that the Concurrent classes tend to be slower than the non-concurrent ones, not to mention the additional level of redirection with the atomic reference. Depending on your thread contention, a naive synchronized solution may actually be faster (and easier to verify for correctness).
Additionally, I think that you can possibly end up with an infinite loop when a SingletonException is thrown during a call to instance.init(). The reason being that a concurrent thread waiting in readEventually will never end up finding its instance (since an exception was thrown while another thread was initializing the instance). Maybe this is the correct behaviour for your case, or maybe you want to set some special value to the instance to trigger an exception to be thrown to the waiting thread.
Having all of these concurrent/atomic things would cause more lock issues than just putting
synchronized(clazz){}
blocks around the getter. Atomic references are for references that are UPDATED and you don't want collision. Here you have a single writer, so you do not care about that.
You could optimize it further by having a hashmap, and only if there is a miss, use the synchronized block:
public static <T> T get(Class<T> cls){
// No lock try
T ref = cache.get(cls);
if(ref != null){
return ref;
}
// Miss, so use create lock
synchronized(cls){ // singletons are double created
synchronized(cache){ // Prevent table rebuild/transfer contentions -- RARE
// Double check create if lock backed up
ref = cache.get(cls);
if(ref == null){
ref = cls.newInstance();
cache.put(cls,ref);
}
return ref;
}
}
}
Consider using Guava's CacheBuilder. For example:
private static Cache<Class<? extends Singleton>, Singleton> singletons = CacheBuilder.newBuilder()
.build(
new CacheLoader<Class<? extends Singleton>, Singleton>() {
public Singleton load(Class<? extends Singleton> key) throws SingletonException {
try {
Singleton singleton = key.newInstance();
singleton.init();
return singleton;
}
catch (SingletonException se) {
throw se;
}
catch (Exception e) {
throw new SingletonException(e);
}
}
});
public static <T extends Singleton> T getSingletonInstance(Class<T> clazz) {
return (T)singletons.get(clazz);
}
Note: this example is untested and uncompiled.
Guava's underlying Cache implementation will handle all caching and concurrency logic for you.
This looks like it would work although I might consider some sort of sleep if even a nanosecond or something when testing for the reference to be set. The spin test loop is going to be extremely expensive.
Also, I would consider improving the code by passing the AtomicReference to readEventually() so you can avoid the containsKey() and then putIfAbsent() race condition. So the code would be:
AtomicReference<T> ref = (AtomicReference<T>) CACHE.get(key);
if (ref != null) {
return readEventually(ref);
}
AtomicReference<T> newRef = new AtomicReference<T>(null);
AtomicReference<T> oldRef = CACHE.putIfAbsent(key, newRef);
if (oldRef != null) {
return readEventually(oldRef);
}
...
The code is not generally thread safe because there is a gap between the CACHE.containsKey(key) check and the CACHE.putIfAbsent(key, ref) call. It is possible for two threads to call simultaneously into the method (especially on multi-core/processor systems) and both perform the containsKey() check, then both attempt to do the put and creation operations.
I would protect that execution of the getSingletonInstnace() method using either a lock or by synchronizing on a monitor of some sort.
google "Memoizer". basically, instead of AtomicReference, use Future.

Categories