I understand that if this was about a HashMap or some other complex object I would still need to add synchronized. But is this also the case for primitives? My intuitive feeling is that I don't need it, but I'm not certain.
-
Well, do you mind that certain threads never get updated values of the integer at all? If you can guarantee that a single thread writes – and no other one does, then you don't need to synchronize. You may also take a look at the [`volatile` keyword](https://stackoverflow.com/questions/106591/what-is-the-volatile-keyword-useful-for), which is about *memory visibility*. – MC Emperor Oct 16 '20 at 10:06
-
I don't mind that they get the previous value, no. – Tigris Oct 16 '20 at 10:08
-
What about a never assigned value, seeing some primitive writes or read are not atomic ? https://stackoverflow.com/a/1006712/2131074 – GPI Oct 16 '20 at 16:31
1 Answers
If you do not add a 'happens before' relation between a read and a write, you could end up with a data race. if there is a data race, all bets are off. The compiler could optimize the code in such a way you will never see the new value.
If you want to have very cheap access, you could do an acquire load and a store release.
AtomicLong.getAcuire
AtomicLong.storeRelease
On the X86 platform every load is an acquire load and every store is a release store. So you will get this totally for free on the hardware level. However it will prevent certain compiler optimizations.
If you care a little bit less for extreme performance, then a volatile would be sufficient. This will give you a sequential consistent load and store. The main issue on the hardware level is that it blocks the CPU from executing any loads till store buffer is drained to the Level 1 cache. A volatile load is equally expensive on a hardware level as an acquire load; the price for sequential consistency is at the write.

- 10,545
- 3
- 23
- 40
-
2Using `getAcquire` will prevent the classical compiler optimization of turning `while (running) {}` into `boolean __localRunning = running; while (__localRunning) {}`. Well, even opaque access does that. – Johannes Kuhn Oct 17 '20 at 03:35