Is the thread master setup safe?

I keep getting mixed answers as to whether this code is thread safe or not. I am working in Java 8.

private final Object lock = new Object();
private volatile Object reference = null;

public Object getOrCompute(Supplier<Object> supplier) {
    if (reference == null) {
        synchronised(lock) {
            if (reference == null) {
                reference = supplier.get();
            }
        }
    }

    return reference;
}

      

My expectation is that given a new instance of this class, multiple calls getOrCompute()

will result in one provider being called, and the result of that provider will be the result of all calls (and future calls) before getOrCompute()

.

+3


source to share


2 answers


This is safe because everything that is done in supplier.get()

must not be reordered with assignment reference

. (Or, more accurately, it shouldn't be reordered when you're doing a volatile read reference

.)

Locking provides exclusivity, while volatile write / read semantics provide visibility. Note that this was only true after Java 5, which was released a long time ago, but you will still find outdated articles on the internet about how double-checked locking (that's the official name of this idiom for that) doesn't work. They were right at the time, but now they are outdated.



Which might be unsafe though the provider itself if it supplies a modified object. But that's another matter.

+3


source


Synchronization is not thread safe. This prevents threads from accessing the object right away, but it has no control over which thread gets it, when, or what it does with the object when it accessed it. Synchronization limits access to only one thread at a time, the thread it first accesses first accesses it.

In this case, the only thing it does is prevent multiple threads from being created for the object. If the object is already initialized, it will be passed to any thread that wants it without thread safety, whatever it is.



Imagine you have one thread that calls this method and instantiates the object, it retrieves it and while it retrieves the object, another thread tries to instantiate it, which it won't be allowed to do as it exists, so it can go directly to retrieve an object, like thread number one, they can now modify the object at the same time, ergo, rather than thread safe. But creating a new object is thread safe in the sense that an object can only be created once.

0


source







All Articles