To perform lock-free and wait-free lazy initialization I do the following:
private AtomicReference<Foo> instance = new AtomicReference<>(null);
public Foo getInstance() {
Foo foo = instance.get();
if (foo == null) {
foo = new Foo(); // create and initialize actual instance
if (instance.compareAndSet(null, foo)) // CAS succeeded
return foo;
else // CAS failed: other thread set an object
return instance.get();
} else {
return foo;
}
}
and it works pretty well except for one thing: if two threads see instance null
, they both create a new object, and only one is lucky to set it by CAS operation, which leads to waste of resources.
Does anyone suggest another lock-free lazy initialization pattern, which decrease probability of creating two expensive objects by two concurrent threads?
instance.get()
because thats how atomic fields work - they lock efficiently (or sequentialize globally), copy data and unlock. In terms of java, an AtomicReference is mapped onto a native, atomic field - which is extremely efficient hence you may never actually "feel" the difference. – Schoolmistress