为什么在Java中同步昂贵?

unj*_*nj2 33 java synchronized

我是Java的新手,我读到Java中synchronized的"非常昂贵".我想知道的是什么是昂贵的,它是如何昂贵的?

谢谢.

Joh*_*ooy 36

也许它没有你想象的那么糟糕

它曾经是可怕的(这可能是你读到它"非常昂贵"的原因).这些模因可能需要很长时间才能消亡

是一篇关于它的好文章

同步有多贵?

由于涉及高速缓存刷新和失效的规则,Java语言中的同步块通常比许多平台提供的关键部分设施更昂贵,这些平台通常用原子"测试和设置位"机器指令实现.即使程序只包含在单个处理器上运行的单个线程,同步方法调用仍然比非同步方法调用慢.如果同步实际上需要争用锁,则性能损失要大得多,因为需要几个线程切换和系统调用.

幸运的是,JVM的持续改进既提高了整体Java程序的性能,又降低了与每个版本同步的相对成本,并且预计将来会有所改进.此外,同步的性能成本经常被夸大.一个众所周知的消息来源指出,同步方法调用比非同步方法调用慢50倍.虽然这种说法可能是正确的,但它也具有很大的误导性,并导致许多开发人员即使在需要的情况下也要避免同步.

话虽如此 - 并发编程仍然可能很慢,但现在并非如此纯粹是Java的错误.精细锁定和粗锁定之间存在权衡.太粗糙显然是坏的,但也可能太精细,因为锁具有非零成本.

考虑争用中的特定资源非常重要.机械硬盘是更多线程可能导致更差性能的示例.


Osc*_*Ryz 13

它很昂贵,因为如果你使用线程,并且许多线程必须经过代码的同步部分,那么一次只能执行其中一个.

这就像一个瓶颈.

使用单个线程时甚至会很昂贵,因为无论如何都必须检查是否允许它运行.

如果减少同步段的使用,您的线程将不必停下来查看它们是否可以运行(当然,它们不必共享数据)

可以在此处找到有关同步如何工作的高级概述

http://img20.imageshack.us/img20/2066/monitor28synchronizatioc.png

Java风格的监视器


pax*_*blo 7

这不是Java特有的.如果没有正确完成,任何多线程环境中的同步都可能被认为是"昂贵的".我不知道是否在Java中特别糟糕.

如果线程使用相同的资源,它会阻止线程并发运行.但是,由于他们确实使用相同的资源,因此没有更好的选择(必须这样做).

问题是人们经常保护范围太大的资源.例如,设计糟糕的程序可能会同步整个对象数组,而不是数组中的每个单独元素(甚至是数组的一部分).

这意味着尝试读取元素7的线程必须等待线程读取或写入元素22.没有必要.如果同步的粒度是在元素级别而不是数组级别,那么这两个线程不会相互干扰.

只有当两个线程试图访问同一个元素时才会出现资源争用.这就是为什么一般规则只是保护尽可能小的资源(当然,受限于同步数量).

但是,说实话,如果由于两个线程争夺单个资源而导致数据损坏,那么它的价格并不高.正确编写您的应用程序,只有在出现性能问题时才会担心("让它先运行然后快速运行"是我最喜欢的口头禅).


Vin*_*nie 5

IBM的这篇文章实际上很好地总结了同步背后的要点.

由于涉及高速缓存刷新和失效的规则,Java语言中的同步块通常比许多平台提供的关键部分设施更昂贵,这些平台通常用原子"测试和设置位"机器指令实现.即使程序只包含在单个处理器上运行的单个线程,同步方法调用仍然比非同步方法调用慢.如果同步实际上需要争用锁,则性能损失要大得多,因为需要几个线程切换和系统调用.

  • 请注意,文章引用的最新Java版本是Java 1.3.该版本于2000年5月发布,并且早已被EOLed发布.虽然基本事实仍然有些相似(Java内存模型改变了一些),但是有大量的优化使得同步在未经测试的情况下非常便宜. (16认同)
  • 当然,在编写多线程代码时,代码块的相互排斥和内存的一致性在根本上是必要的,并且Java中没有"巧妙"的技巧(只是巧妙地破解)以避免它们.如果你的两个线程必须进行交互,你必须同步 - 纯粹和简单.粒度同步是唯一剩下的问题. (3认同)