为什么java中的synchronized关键字慢?

时间:2016-02-21 19:46:27

标签: java multithreading


   最近我与朋友讨论了java中的并发问题,他问我为什么同步关键字围绕一块代码或方法很慢。我回答说它很慢,因为它争用对象监视器。它还提供了一个在保证之前发生的事情,并且它必须将其缓存中的所有变量与主存储器同步,并且在块的末尾它必须刷新缓存。它还可以防止编译器以及指令的cpu重新排序。不过,他说这些确实会导致经济放缓,但这并不是性能下降的主要原因。基本上即使线程命中同步块时没有争用,它也会从用户模式切换到内核模式,线程必须保存状态,然后当它离开块时,它必须再次重新加载状态。我试图在网上找到描述这个但我找不到的文献。我想知道是否有人能证实这是正确的?为什么java线程在达到同步时进入内核模式,为什么不在此之前?这与此link中提出的问题不同,因为我问的是从用户模式到内核模式的显式切换,这个导致性能下降?

1 个答案:

答案 0 :(得分:1)

你朋友说的绝对是错误的。

对于同步这么昂贵的事情,你几乎是对的。最困难的部分实际上是(特别是在x86 / x86_64处理器上)比较和交换指令,它比较并设置当前线程作为锁的所有者。在x86 / x86_64 cmpxchg指令用于此,当它到达主存储器时,它比任何常规指令慢。然后正如你所提到的,内存障碍减慢了缓存。

在其他一些体系结构上,尤其是基于RISC的体系结构中,通常使用通常被动加载的独占/存储专用,这通常要快得多。所以这可能因架构而异。

无论如何,Java(以及任何其他语言)试图避免进入内核,大多数静默文本实现只在几次重试后执行它,因为它几乎清楚线程需要被挂起。