【问题标题】:Are Synchronized Methods Slower In Single Threaded Applications?单线程应用程序中的同步方法是否更慢?
【发布时间】:2009-06-10 03:10:35
【问题描述】:

在过去的几分钟里,我一直在自言自语地争论这个问题,我看到了是和否的原因。这源于查看Java HashMap vs. Hashtable 的答案并看到一些人说 Hashtable 实际上更慢。

在我看来,如果在单个线程中运行,同步方法应该与它的非同步方法完全没有区别,因为同步操作不应该阻塞任何东西。也就是说,我想编译器会以不同的方式处理这两种情况,这就是人们说同步速度较慢的原因。

并不是说这绝对是决定性的,但我对 HashMap 与 Hashtable 进行了一些简单的测试,发现速度差异不大。

【问题讨论】:

  • 瓶颈在于你的算法。因此,同步开销应该很小。

标签: java multithreading synchronization


【解决方案1】:

是的,使用同步的单头 Java 程序可能比不使用同步的情况稍慢。对于早期的 Java 版本,同步是昂贵的。然而,对于任何现代版本,uncontended 同步非常便宜。我不会担心这个。

请注意,Java 6 已经和 Java 7 对锁定进行了很好的优化:

  • 锁粗化
  • 锁定省略
  • 自适应自旋锁定
  • 偏向锁定

有关详细信息,请参阅Java SE 6 Performance White Paper。另请注意,在多核 CPU 上,非竞争同步似乎比在单核 CPU 上更昂贵,这可能是由于 Java 内存模型要求同步强制本地 CPU 缓存与其他 CPU 共享,或者其他一些内存障碍。例如,阅读Do Java 6 threading optimizations actually work? - Part II。 (第一部分不如第二部分深刻。)

【讨论】:

  • +1 用于提及争用 - 同步本身很便宜。
【解决方案2】:

是的。由于维护锁的额外开销,它们会稍微慢一些。

【讨论】:

  • ...如果 JIT 无法确定在这种情况下不需要维护锁...
【解决方案3】:

使用同步数据结构时,减速不取决于“多少”被阻塞。获取或释放锁的行为很慢,因为它通常涉及系统调用之类的东西(上下文切换在任何平台上都很慢)。在像典型 JVM 这样的 JIT 环境中,理论上可以在只有一个线程运行时优化所有锁定/解锁调用,但每当另一个线程启动时就必须适当地使其无效。

请注意,Linux 的 futexes 之类的东西不必进行系统调用,除非存在争用,但使用它们仍然比无操作慢。

【讨论】:

  • 除非操作系统是 CPU 热插拔我猜;那么 JVM 就无法做出这样的假设?
  • 问题不在于是否有多个CPU,而在于JVM内部是否有多个线程。诚然,了解是否有多个 CPU 会扩大此优化的适用性,但当有多个 CPU 时运行单线程应用程序更为常见。我试图表达的观点是,我不知道任何类似于零成本异常的互斥锁。
  • 如果你的代码唯一做的事情是获取和释放锁,是的,它会很慢。只要锁足够少,代码中的任何减速都将是最小的,尤其是任何最近的 JVM。非竞争锁定不再昂贵。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 2021-12-27
  • 2014-04-09
相关资源
最近更新 更多