基于以下理解:
我想知道因为所有对象都是在公共堆上创建的。如果多个线程创建对象然后为了防止数据损坏,必须进行一些必须发生的序列化以防止多个线程在相同位置创建对象。现在,有了大量的线程,这个序列化将导致一个很大的瓶颈。 Java如何避免这个瓶颈?或者我错过了什么?
任何帮助赞赏。
基于以下理解:
我想知道因为所有对象都是在公共堆上创建的。如果多个线程创建对象然后为了防止数据损坏,必须进行一些必须发生的序列化以防止多个线程在相同位置创建对象。现在,有了大量的线程,这个序列化将导致一个很大的瓶颈。 Java如何避免这个瓶颈?或者我错过了什么?
任何帮助赞赏。
现代VM实现为每个线程保留堆上的自己区域以创建对象。因此,只要此区域未满(然后垃圾收集器移动幸存的对象)就没有问题。
进一步阅读: TLAB如何工作 在Sun的JVM中。 Azul的VM 使用略有不同的方法(查看“新线程和堆栈布局”),文章展示了JVM可能在幕后执行的一些技巧,以确保现在的Java速度。
主要思想是保持每个线程(非共享)区域分配新对象,就像在C / C ++堆栈上分配一样。复制垃圾收集非常快速地释放短期对象,少数幸存者(如果有的话)被移动到不同的区域。因此,创建相对较小的对象非常快 锁定免费。
无锁分配非常重要,尤其是问题所在 multithreaded environment
。它还允许存在真正的无锁算法。即使算法本身是无锁的,但新对象的分配是同步的,整个算法也是有效同步的,并且最终可扩展性较差。
java.util.concurrent.ConcurrentLinkedQueue
这是基于 Maged M. Michael Michael L. Scott的作品 是一个典型的例子。
如果一个对象被另一个线程引用会发生什么? (由于讨论要求)
那个对象(称之为 A
)将被转移到一些“幸存者”区域。幸存区域的检查频率低于ThreadLocal区域。它包含,如名称所示,其引用设法逃脱的对象,或特别是 A
设法活着。复制(移动)部分发生在某个“安全点”(安全点排除正确的JIT代码),因此垃圾收集器确保该对象未被引用。更新对象的引用,发布必要的内存围栏,应用程序(java代码)可以继续。进一步阅读此内容 简单的场景。
对非常感兴趣的读者,如果可能的话,咀嚼它:非常先进 无气GC算法
现代VM实现为每个线程保留堆上的自己区域以创建对象。因此,只要此区域未满(然后垃圾收集器移动幸存的对象)就没有问题。
进一步阅读: TLAB如何工作 在Sun的JVM中。 Azul的VM 使用略有不同的方法(查看“新线程和堆栈布局”),文章展示了JVM可能在幕后执行的一些技巧,以确保现在的Java速度。
主要思想是保持每个线程(非共享)区域分配新对象,就像在C / C ++堆栈上分配一样。复制垃圾收集非常快速地释放短期对象,少数幸存者(如果有的话)被移动到不同的区域。因此,创建相对较小的对象非常快 锁定免费。
无锁分配非常重要,尤其是问题所在 multithreaded environment
。它还允许存在真正的无锁算法。即使算法本身是无锁的,但新对象的分配是同步的,整个算法也是有效同步的,并且最终可扩展性较差。
java.util.concurrent.ConcurrentLinkedQueue
这是基于 Maged M. Michael Michael L. Scott的作品 是一个典型的例子。
如果一个对象被另一个线程引用会发生什么? (由于讨论要求)
那个对象(称之为 A
)将被转移到一些“幸存者”区域。幸存区域的检查频率低于ThreadLocal区域。它包含,如名称所示,其引用设法逃脱的对象,或特别是 A
设法活着。复制(移动)部分发生在某个“安全点”(安全点排除正确的JIT代码),因此垃圾收集器确保该对象未被引用。更新对象的引用,发布必要的内存围栏,应用程序(java代码)可以继续。进一步阅读此内容 简单的场景。
对非常感兴趣的读者,如果可能的话,咀嚼它:非常先进 无气GC算法
没有.JVM有各种各样的技巧,以避免在“新”时出现任何类型的简单序列化。
有时。我写了一个递归方法,生成整数排列并从中创建对象。该方法的多线程版本(来自root = task的每个分支,但并发线程数限制为核心数)并不快。并且CPU负载不高。任务没有共享任何对象。从两种方法中删除对象后,多线程方法的速度提高了约4倍(6个核心)并使用了100%的CPU。在我的测试用例中,这些方法产生了大约4,500,000个排列,每个任务1500个。 我认为TLAB没有用,因为它的空间有限(见: 线程本地分配缓冲区)。