【问题标题】:How heavy are Java Monitors?Java 监视器有多重?
【发布时间】:2011-05-03 09:14:34
【问题描述】:

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

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

【问题讨论】:

  • Java 对象带有内置的轻量级锁。无论您是否锁定对象,都会使用此内存。简而言之,Java 被设计和优化为支持每个对象的锁定。

标签: java performance synchronization monitor


【解决方案1】:

您已经支付了(大部分,并且在低竞争中)使用 Java 让监视器周围存在的惩罚......不使用它们毫无意义。特别是在低争用情况下,它们非常便宜(参见Items 2.1, 2.2, 2.3 hereItem #1 here),并且JVM 可以针对许多情况完全优化它们。如果您只暂时使用对象的监视器,JVM 将使其“足够大”(这意味着它以位翻转开始,可能会针对简单的争用情况扩展为堆栈分配的原子标志,并且在持续争用下分配一个 objectmonitor 用于它;随着争用的减弱,所有这些都将展开回低开销的情况下)并稍后回收空间。在某种程度上锁定这些对象是应用程序端的“正确的事情”,我会说去吧。

但是,这里有一种设计的味道。锁定这么多对象听起来不太好。此外,如果您有任何顺序锁定条件,您将无法推断潜在的死锁。我建议您通过有关应用程序的更多详细信息来扩充您的问题,我们可以询问锁定大量对象是否正确。

presentation by Dave Diceblog entry is a treasure trove of sync-on-Java information 对 Java6 同步的工作原理提供了一些有用的见解。如果您真的非常关心完整的对象监视器结构有多大(将在有争议的情况下发挥作用),code is here。 HotSpot internals wiki 页面也有一些good in-depth information

【讨论】:

  • 使用 Java 并不意味着我已经为所有可能的性能损失预先支付了费用……无论如何,这绝对是一个设计问题。我的 C++ 鼻子确实能闻到气味,但我没有使用过 Java 气味……我实际上并不担心死锁,因为操作简短而简单。在这种情况下,很容易抛出“同步”,并保持安全。然而我担心这种扩展性会有多好(我知道在 Win32 中不会,因为内核对象很昂贵)。
  • @eran:明白。如果我们对应用程序有更多了解,我们可以深入研究它。但是鉴于您告诉我们的内容,我想说除非您有可衡量的性能问题,否则请不要担心。在无争议的情况下,您已经支付了几乎所有的罚款;在某处为monitorenter/exit翻转一个已经分配的位有一些很小的成本。如果您确实看到了一些重要的争论,您可能需要更深入地挖掘。
  • @eran:如果这是一个高性能应用程序,您愿意为此投入一些严重的低级注意力,并且想要深入的理论,请查看 Herlihy 的多处理器编程艺术,elsevier.com/wps/find/bookdescription.cws_home/714091/… 警告:很深的东西。但是所有内容都可以使用 Java 代码和分析。
  • 感谢您的回答,andersoj。这将接近生产,只是试图利用这个场合并更好地理解基本的 Java 特性。
  • “我其实并不担心死锁,因为操作很短很简单。” 当心!这些属性并不能保证不会出现死锁。
【解决方案2】:

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

在无竞争的情况下,Java 互斥体仅由标志字中的 2 位组成。 JVM 仅在互斥体竞争时将重量级 OS 锁对象与 Java 互斥体关联,然后在互斥体已被所有线程退出时释放 OS 锁。

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


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

  • 在早期的 Java 版本中,互斥锁的成本要高得多。
  • 自 JavaOne 2006 论文以来可能已经取得了一些进展……无论是否发表。

【讨论】:

  • +1 我没有找到的好资源。希望他们能尝试将这些东西汇总到一个地方。
【解决方案3】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    相关资源
    最近更新 更多