Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the return statement atomic?

I pasted some code about Java concurrency:

public class ValueLatch <T> {

    @GuardedBy("this") private T value = null;
    private final CountDownLatch done = new CountDownLatch(1);

    public boolean isSet() {
        return (done.getCount() == 0);
    }

    public synchronized void setValue(T newValue) {
        if (!isSet()) {
            value = newValue;
            done.countDown();
        }
    }

    public T getValue() throws InterruptedException {
        done.await();
        synchronized (this) {
            return value;
        }
   }

}

Why does return value; need to be synchronized???

Is the return statement not atomic??

like image 500
Li Yunlei Avatar asked Nov 13 '18 15:11

Li Yunlei


Video Answer


3 Answers

The return statement needs to perform a read operation over value.

The read operation is atomic for most primitives, but you're dealing with a generic, meaning you won't know value's type.

For that reason, the return should be synchronized.

like image 109
ricol070 Avatar answered Oct 29 '22 15:10

ricol070


The return does not need to be synchronized. Since CountDownLatch.countDown() is not called until after the value is set for the last time, CountDownLatch.await() ensures that value is stable before it is read and returned.

The developer who wrote this was probably not quite sure of what he was doing (concurrency is difficult and dangerous) or, more likely, his use of the GuardedBy annotation on value caused his build system to emit a warning on the return, and some other developer synchronized it unnecessarily just to make the warning go away.

I say 'some other developer', because this class otherwise seems to be specifically designed to allow getValue() to proceed without locking once the value has been set.

like image 43
Matt Timmermans Avatar answered Oct 29 '22 13:10

Matt Timmermans


return value does not need to be synchronized:

  • reads of references is atomic according to the JLS: "Writes to and reads of references are always atomic, ..."
  • each thread reading value is guaranteed to so see its latest value as according to the Java Memory Model value = newValue happens-before done.countDown(), which happens-before done.await(), which happens-before return value. By transitivity value = newValue thus happens-before return value.
like image 45
michid Avatar answered Oct 29 '22 13:10

michid