Java监视器有多重?

时间:2010-11-01 11:44:18

标签: java performance synchronization monitor

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

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

3 个答案:

答案 0 :(得分:14)

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

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

这个presentation by Dave Dice提供了有关Java6同步如何工作的有用见解,以及blog entry is a treasure trove of sync-on-Java information。如果你真的非常关心一个完整的对象监视器结构是多么“大”(将在竞争情况下发挥作用),code is here。 HotSpot内部维基页面也有一些good in-depth information

答案 1 :(得分:6)

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

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

可以在Javaone 2006的this presentation幻灯片9到23中找到有关如何实现Java互斥体的概述。


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

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

答案 2 :(得分:0)

我认为Collections.synchronizedCollection允许一个线程访问该集合。但是存在创建监视器的问题。