Search code examples
javajava.util.concurrentconcurrent-programming

in java concurrent programming, is need to using synchronized when read value?


this class can be used in multi thread because it is thread-safe.

public class Hello {
    private int value = 0;

    public synchronized int get() {
        return value;
    }

    public synchronized void set(int value) {
        this.value = value;
    }
}

i know that the reason that we must use synchronized when get() ,besides set() is memory visibility.

and java volatile keyword can be used for memory visibility.

so then.. this class is also thread-safe??

public class Hello {
    private volatile int value = 0;

    public int get() {
        return value;
    }

    public synchronized void set(int value) {
        this.value = value;
    }
}

Solution

  • In your specific example, you don't need that extra synchronized. Given that you have already mentioned memory visibility (aka happens-before), I won't go deeper to explain this.

    However, it does not apply generally. There are several assumptions in your example making it enough to simply use volatile

    1. Type of value

      Although you are simply doing a simple retrieval/assignment of value, it is not always guaranteed to be atomic for all data type. Iirc, Java only guarantee that such operation is atomic for int and types smaller that int. Which means, for example, if value is of type long, even you have declared it with volatile, you may still corrupt value with your above example

    2. Operations on value

      Ok, let's assume it is an int. In your example, you are simply getting and assigning an int for which the operation is atomic, hence simply using volatile is enough. However if you have another method doing something like value++, using volatile is not sufficient. In such case, you may either consider using Atomic* or use synchronized


    Update: I later found that JLS https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 mentioned that using volatile would enforce atomic read/write on double/long. So my original point 1 was actually wrong