synchronized
static
class Counter { private int value = 0; public synchronized int getValue() { return value++; } public int getSameValue() { synchronized(this) { return value++; } } }
class Counter { private AtomicInteger value = new AtomicInteger(0); public int getValue() { return value.getAndIncrement(); } }
In computing, a memory model describes the interactions of threads through memory and their shared use of the data.[1]
Compilers are allowed to reorder the instructions, when this does not affect the execution of the thread in isolation. [2]
A = B = 0 // thread 1 r2 = A; B = 1 // thread 2 r1 = B; A = 2;
r1
r2
r1 == 1
r2 == 2
volatile
If one action happens-before another, then the first is visible to and ordered before the second [3]
final
++
--
class VolatileExample { int x = 0; volatile boolean flag = false; public void writer() { x = 42; flag = true; } public void reader() { if (flag == true) { System.out.println(x); // guaranteed to see 42. } } }
class AtomicExample { private int value = 0; private AtomicBoolean flag = new AtomicBoolean(false); public void writer() { value = 42; flag.set(true); } public void reader() { while (!flag.get()) {} // busy wait here System.out.println(value); // guaranteed to see 42. } }
public synchronized void doSomething() { /* ... */ } public void doSomethingElse() { synchronized(this.attribute) {/* ... */} }
class ThreadExample { public void run() { Integer value = 42; var t = new Thread(() -> value *= 2 ); // value is 42 t.start(); t.join(); // value is guaranteed to be 84; } }
Is this correct?
class Foo { private Helper helper = null; public Helper getHelper() { if (helper == null) { synchronized(this) { if (helper == null) helper = new Helper(); } } return helper; } }