【问题标题】:A use-case for synchronized(new Object())synchronized(new Object()) 的用例
【发布时间】:2013-05-18 16:05:39
【问题描述】:

在最近的answer 中我建议可以通过synchronizing 在包含我们需要为volatile 的变量的对象上实现volatile 的功能(asker 无权访问该变量在代码)。

这让我想到我实际上不需要阻塞包含对象,我只需要实现内存屏障。由于synchronized 实现了两个 同步 内存屏障,如果我需要的只是内存屏障(在这种情况下),使用synchronized(new Object()) 实际上会更好吗实现我的内存屏障确保永远不会争用锁?

【问题讨论】:

标签: java multithreading synchronization shared-memory


【解决方案1】:

如此处所述:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#synchronization synchronized(new Object()) 被认为是一个 noop,并且可以被编译器完全删除。您不会从中获得内存障碍。

【讨论】:

  • 什么可以实现我想要的 - 没有锁争用的内存屏障?
【解决方案2】:

除了@assylias 的非常好的点,还要考虑synchronized 没有按规范实现内存屏障。只是这就是它在当今典型的 CPU 内存架构上实现的方式。规范只保证两个线程获取相同锁时会发生什么。

无论如何,如果您不关心规范,而只关心现实世界的实现,那么为什么不引入您自己的 volatile 变量并在需要内存屏障时简单地写入它呢? 你写给哪个volatile 无关紧要,只要我们谈论的是你的synchronized(new Object()) 想法所暗示的一组受限架构。

【讨论】:

  • 我认为这是我遗漏的关键点 - 障碍仅适用于特定锁定对象的所有共享者。尽管关于这个主题的大多数讨论都提到了刷新缓存,但实现只是将缓存值从一个 cpu 推送到另一个 cpu 是很有可能的。
  • 在问题中,提问者想要调用他们无法从多个线程控制的对象的set... 方法。变量不能设为volatile
  • 是的,我希望随着执行单元(核心或其他)数量的增加而发生这种情况。在大规模并行系统中没有缓存一致性,我认为现在主流已经坚定地走上了这条道路。
  • 不幸的是,没有 Java 原语具有“内存屏障”的确切语义。
  • 对不起,我认为实际上 执行写入的线程的所有操作对执行读取的线程都是可见的---这非常接近真正的记忆障碍!
【解决方案3】:

使用synchronized(new Object()) 来实现我的内存屏障并确保永远不会争用锁会更好吗?

没有。 JVM 可以很容易地证明这个锁不能被两个线程访问(因为它是一个线程局部变量)并且几乎肯定会把它变成一个空操作,即完全删除synchronized 语句。

【讨论】:

  • 那么如何在不设置实际变量 volatile 的情况下实现像 volatile 这样的内存屏障,同时最小化/消除锁争用?
  • @OldCurmudgeon 我在 sun.misc 包中看到了一些东西,但不确定它是在 JDK 7 还是 8 中(例如:unsafe.load / unsafe.store) - 无法挖掘出来现在。
猜你喜欢
  • 2016-09-05
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 2014-02-10
  • 2015-08-28
  • 2014-08-25
  • 2012-03-10
相关资源
最近更新 更多