It’s known that simple x++ is not an atomic operation, but in fact is read-increment-write operation. That is why it should be synchronized. But what about get()? I have read it should be synchronized too, but could someone explain me why? To avoid memory consistency errors by introducing happens-before relationship?
What about a situation when get() is called very often by multiple threads and the value is rarely changed. Isn’t synchronized get() slowing them down? Are there any other ways to achieve synchronization in that scenario (not using AtomicInteger)? Would volatile keyword work here?
public class Counter {
private int value;
public synchronized int get() { return value; }
public synchronized int increment() { return ++value; }
public synchronized int decrement() { return --value; }
}
Thanks!
edit:
I would like to make myself clear. By using volatile I meant introducing that keyword and removing synchronized in get() method. I was wondering if it will make it thread-safe but also more efficient if many threads are reading the value and one is rarely changing it.
First off, you should be using
AtomicIntegerif you can. I’m not sure why you would not use it.Yes except not for the
++.AtomicIntegerprovides a safe increment without locking. If you want to roll your own (for some crazy reason) then you will need the blocking or you need to duplicate theAtomicIntegerinternal spin mechanisms.AtomicIntegerwraps avolatile intto provide its functionality. When you access thevolatilefield you cross a memory barrier on theget()as well. You need to cross that memory barrier to ensure that if another thread has updated the value, the thread calling theget()sees the update. Otherwise, a thread could be working with a outdated value.