Java监视器有多重?

era*_*ran 15 java performance synchronization monitor

假设我有一个包含数千个对象的数组,以及可能访问每个对象的少量线程.我想保护对其中一个对象方法的访问.最简单的方法是将该方法声明为synchronized.但是,这可能会导致创建数千个监视器,无论它们是以何种方式实现的.如果这是Win32,我永远不会创建数千个内核对象,如Mutex,但CRITICAL_SECTION 可能是合理的.我想知道Java的情况如何.鉴于争用的可能性很低,监视器的使用是否会超过他们所需的大量内存?在Java中使用这种低粒度同步的做法有多常见?

(显然有一些解决方法,例如使用更小的同步对象数组,可以使用一些哈希来访问.我不是在寻找一个实用的解决方案,我正在寻找一个洞察力).

and*_*soj 14

你已经支付了(大多数,并且在低争用中)使用Java监视器的惩罚...没有意义不使用它们.特别是在低竞争情况下,它们非常便宜(参见此处的2.1,2.2,2.3 第1项),JVM可以在很多情况下完全优化它们.如果你只是暂时使用对象的监视器,那么JVM会使它"足够大"(意味着它从位翻转开始,可能会因为简单的争用情况而扩展到堆栈分配的原子标志,并且在持久争用下会分配一个objectmonitor)它;所有这些都将在争用减少时展开回低开销情况)并稍后回收空间.如果锁定这些对象是应用程序方面的"正确的东西",我会说它去做.

但是,这里有一种设计气味.锁定这么多物体听起来不太好.此外,如果您有任何顺序锁定条件,您将无法推断潜在的死锁.我建议你用关于应用程序的更多细节来扩充你的问题,我们可以问一下锁定大型对象池是否正确.

演示文稿由Dave骰子给出了一些有益的见解同步如何工作的Java6,这博客条目是同步的Java的信息宝库.如果你真的非常关心一个完整的对象监视器结构是多么"大"(在竞争情况下会发挥作用),代码就在这里.HotSpot内部维基页面也有一些很好的深入信息.


Ste*_*n C 6

Java互斥体足够便宜,你可以拥有数十万个同步对象而不会注意到它.

在非竞争情况下,Java互斥体仅包含标志字中的2位.当互斥锁争用时,JVM仅将重量级OS锁定对象与Java互斥锁关联,然后在所有线程退出互斥锁时释放操作系统锁定.

有关如何实现Java互斥体的概述可以在Javaone 2006 演示文稿的幻灯片9到23中找到.


请注意,互斥锁的实现和性能可能取决于您使用的Java的供应商/版本以及您运行的平台.

  • 在Java早期版本中,互斥量明显更高.
  • 自JavaOne 2006论文以来,可能已经取得了一些进展......是否已经发表.