Java 监视器有多重?
假设我有一个包含数千个对象的数组,以及可能访问每个对象的少量线程。我想保护对对象方法之一的访问。最简单的方法是将该方法声明为synchronized
。然而,这可能会导致创建数千个监视器,无论它们以何种方式实现。如果这是 Win32,我永远不会创建数千个内核对象(例如 Mutex),但 CRITICAL_SECTIONs 可能是合理的。我想知道Java中的情况如何。鉴于争用的可能性很低,监视器的使用是否会超出其所需的绝对内存量?在 Java 中使用这种低粒度同步的做法有多常见?
(显然有一些解决方法,例如使用更小的同步对象数组,将使用一些哈希来访问这些对象。我不是在寻找实用的解决方案,而是在寻找洞察力)。
Say I have an array of thousands of objects, and a small number of threads that might access each of the objects. I want to protect the access to one of the objects methods. Easiest way would be to declare that method as synchronized
. However, that might result in creating thousands of monitors, whichever way they are implemented. If this were Win32, I'd never create thousands of kernel objects such as Mutex, but CRITICAL_SECTIONs might be plausible. I'm wondering what's the case in Java. Given the chance of contention is low, would the use of monitors impose more than the sheer amount of memory they require? How common a practice is it to use such low granularity synchronization in Java?
(There are obviously workarounds such as using a much smaller array of synchronization objects, which will be accessed using some hash. I'm not looking for a practical solution, I'm looking for an insight).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您已经为使用 Java 来使用监视器付出了(大部分且低争用的)代价……不使用它们是没有意义的。特别是在低争用情况下,它们非常便宜(请参阅第 2.1、2.2、2.3 项这里和这里的第#1项),并且 JVM 可以优化它们在许多情况下完全离开。如果您只是暂时使用对象的监视器,JVM 会使其“足够大”(意味着它以位翻转开始,对于简单的争用情况可能会扩展为堆栈分配的原子标志,并且在持久争用下,会为对象分配一个对象监视器)随着争用的减少,所有这些都将被展开回低开销的情况)并稍后回收空间。如果锁定这些对象在应用程序端是“正确的事情”,我会说继续这样做。
然而,这里有一种设计的味道。锁定这么多对象听起来不太好。此外,如果您有任何顺序锁定条件,您将无法推断潜在的死锁。我建议您用有关应用程序的更多详细信息来补充您的问题,我们可以询问锁定大量对象是否是正确的事情。
Dave Dice 的演示对 Java6 同步的工作原理提供了一些有用的见解,并且博客条目是 Java 同步信息的宝库。如果您真的非常关心完整的对象监视器结构有多大(将在有争议的情况下发挥作用),代码在这里。 HotSpot 内部 wiki 页面还提供了一些深入的信息。
You have already paid (most of, and in low-contention) the penalty for having the Monitors around by using Java... no sense not using them. Particularly in the low-contention case, they are very cheap (see Items 2.1, 2.2, 2.3 here and Item #1 here), and the JVM can optimize them away entirely for a number of cases. If you only use the object's monitor transiently, the JVM will make it "big enough" (meaning it begins as bit-flipping, might expand for simple contention cases to a stack-allocated atomic flag, and under persistent contention have a objectmonitor allocated for it; all of these will be unrolled back to the low-overhead case as contention abates) and reclaim the space later. To the extent that locking on these objects is the "right thing" on the application side, I'd say go for it.
However, there's a design smell here. Locking on so many objects doesn't sound great. Furthermore, if you have any sequential locking conditions, you're not going to be able to reason about potential deadlocks. I suggest you augment your question with more detail about the application, and we can ask whether locking on a large pool of objects is the Right Thing.
This presentation by Dave Dice gives some useful insight into how Java6 synchronization works, and this blog entry is a treasure trove of sync-on-Java information. If you really, really care about how "big" a full-on objectmonitor structure is (will come into play in the contended case), the code is here. The HotSpot internals wiki page also has some good in-depth information.
Java 互斥体非常便宜,您可以拥有数十万个同步对象而不会注意到它。
在无竞争的情况下,Java 互斥体仅由标志字中的 2 位组成。 JVM 仅在互斥体发生争用时才将重量级操作系统锁对象与 Java 互斥体相关联,然后在所有线程退出该互斥体时释放操作系统锁。
有关 Java 互斥体如何实现的概述可以在 此演示文稿来自 Javaone 2006。
请注意,互斥体的实现和性能可能取决于您所使用的 Java 供应商/版本以及所运行的平台。
Java mutexes are cheap enough that you can have hundreds of thousands of synchronized objects and not notice it.
In the uncontended case, a Java mutex consists of just 2 bits in the flags word. The JVM only associates a heavy-weight OS lock object with a Java mutex when the mutex is contended, and then releases the OS lock when the mutex has been exited by all threads.
An overview of how Java mutexes are implemented may be found in slides 9 to 23 of this presentation from Javaone 2006.
Note that the implementation and performance of mutexes is liable to depend on the vendor / release of Java that you are using, and the platform that you are running on.
我认为 Collections.synchronizedCollection 让一个线程访问集合。然而,创建监视器的问题仍然存在。
I think Collections.synchronizedCollection let one thread access the collection. However the problem of creating monitors exists.