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;
}
}
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
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
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