英文:
Do I need synchronization when only one thread writes an integer, and it doesn't matter if the other threads get older information?
问题
我理解如果涉及到HashMap或其他一些复杂对象,我仍然需要添加同步。但是对于基本类型是否也是这种情况呢?我的直觉是不需要,但我不太确定。
英文:
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.
答案1
得分: 2
如果您不在读取和写入之间添加一个“发生在之前”的关系,可能会导致数据竞争。如果存在数据竞争,一切皆有可能。编译器可以以这样的方式优化代码,以至于您永远看不到新值。
如果您希望获得非常便宜的访问权,可以执行获取加载和存储释放。
例如:https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html
AtomicLong.getAcuire
AtomicLong.storeRelease
在X86平台上,每次加载都是获取加载,每次存储都是释放存储。因此,在硬件级别上,您将完全免费获得这些功能。但是,它将阻止某些编译器优化。
如果您对极端性能不太关心,那么使用volatile就足够了。这将为您提供顺序一致的加载和存储。在硬件级别上的主要问题是,它会阻止CPU执行任何加载操作,直到存储缓冲区排入一级缓存为止。在硬件级别上,volatile加载与获取加载一样昂贵;顺序一致性的代价在于写入。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论