代码之家  ›  专栏  ›  技术社区  ›  Eran

Java监视器有多重?

  •  15
  • Eran  · 技术社区  · 14 年前

    假设我有一个由数千个对象组成的数组,以及可能访问每个对象的少量线程。我想保护对其中一个对象方法的访问。最简单的方法是将该方法声明为 synchronized . 然而,这可能会导致创建数千个监视器,无论它们是以何种方式实现的。如果这是win32,我绝不会创建数千个内核对象,如mutex,但关键的\u部分 可以 言之有理。我想知道Java中的情况。考虑到竞争的可能性很低,监视器的使用会比它们所需的内存量更大吗?在Java中使用这样的低粒度同步有多普遍?

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

    3 回复  |  直到 14 年前
        1
  •  14
  •   Bill the Lizard    13 年前

    你已经支付了(大部分和低争用)使用Java来监视监视器的惩罚。没有理由不使用它们。特别是在低争用情况下,它们非常便宜(见 Items 2.1, 2.2, 2.3 here Item #1 here )并且JVM可以在许多情况下完全优化它们。如果您只是临时使用对象的监视器,那么jvm将使其“足够大”(意味着它以位翻转开始,可能会将简单的争用情况扩展为堆栈分配的原子标志,并且在持久争用下,会为其分配一个对象监视器;所有这些都将在k到低开销的情况下,随着争用的减少)并稍后回收空间。在某种程度上,锁定这些对象是应用程序端的“正确的事情”,我想说的是执行它。

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

    这个 presentation by Dave Dice 提供了一些有用的关于Java6同步如何工作的见解,并且 blog entry is a treasure trove of sync-on-Java information . 如果您真的非常关心一个完整的ObjectMonitor结构有多“大”(将在有争议的情况下发挥作用),那么 code is here . 热点内部wiki页面也有一些 good in-depth information

        2
  •  6
  •   Stephen C    9 年前

    Java互斥很便宜,可以有成千上万个同步对象而不注意它。

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

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


    请注意,互斥体的实现和性能很容易依赖于正在使用的Java的供应商/发布,以及您正在运行的平台。

    • 在早期的Java版本中,互斥的代价要高得多。
    • 自从JavaOne 2006年的论文以来,可能已经有了很大的进步…是否出版。
        3
  •  0
  •   Nageswara Rao    14 年前

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