【问题标题】:Do I need synchronization when only one thread writes an integer, and it doesn't matter if the other threads get older information?当只有一个线程写入整数时是否需要同步,而其他线程是否获得较旧的信息并不重要?
【发布时间】:2020-10-16 09:51:25
【问题描述】:

我知道,如果这是关于 HashMap 或其他一些复杂对象,我仍然需要添加同步。但是对于原语来说也是这样吗?我的直觉感觉是我不需要它,但我不确定。

【问题讨论】:

  • 好吧,你介意某些线程根本不会得到整数的更新值吗?如果您可以保证单个线程写入 - 而没有其他线程可以,那么您不需要同步。你也可以看看volatile keyword,这是关于内存可见性的。
  • 我不介意他们得到以前的值,不。
  • 一个从未赋值的值,看到一些原始的写入或读取不是原子的怎么办? stackoverflow.com/a/1006712/2131074

标签: java multithreading synchronized


【解决方案1】:

如果您不在读取和写入之间添加“发生在之前”的关系,您最终可能会出现数据竞争。如果有数据竞赛,所有的赌注都会被取消。编译器可以优化代码,使您永远不会看到新值。

如果您想获得非常便宜的访问权限,您可以进行获取加载和存储发布。

例如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 执行任何加载,直到存储缓冲区耗尽到 1 级缓存。在硬件级别上,易失性负载与获取负载一样昂贵;顺序一致性的代价在于写入。

【讨论】:

  • 使用getAcquire 将阻止将while (running) {} 转换为boolean __localRunning = running; while (__localRunning) {} 的经典编译器优化。好吧,即使是不透明的访问也能做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多