JVM 如何确保新对象的内存分配的线程安全
让我们假设这将同时在真正的并行环境(一个 VM)中发生:
// Thread 1:
new Cat()
// Thread 2:
new Dog()
// Thread 3:
new Mouse()
JVM 如何确保堆上内存分配的线程安全?
堆是所有线程的一个,它有自己的内部数据。
为简单起见,假设有一个简单的压缩垃圾回收器实现 ,-XX:+UseSerialGC -XX:+UseParallelGC,使用简单的增量指针来标记可用空间的开始和 Eden 中的一个连续可用空间(堆)。
当为 Cat、Dog 和 Mouse 实例分配堆空间时,线程之间必须存在某种同步,否则它们很容易最终相互覆盖。这是否意味着每个新操作员都隐藏在一些同步块中?这样,许多“无锁”算法实际上并不是完全无锁;)
我假设内存分配是由应用程序线程本身同步进行的,而不是由另一个专用线程进行的。
我知道 TLAB或线程本地分配缓冲区。它们允许线程在 Eden 中具有单独的内存区域以进行分配,因此不需要同步。但我不确定TLAB是否默认设置,它是一些非常晦涩的HotSpot功能。注意:不要混淆TLAB和变量!ThreadLocal
我还假设,对于更复杂的垃圾回收器,如G1或非压缩垃圾回收器,必须维护更复杂的堆结构数据,例如CMS的可用块列表,因此需要更多的同步。
更新:请让我澄清这一点。我接受HotSpot JVM实现和带有和不具有活动TLAB的变体的答案。
更新:根据我的快速测试,TLAB默认设置为打开,在我的64位JDK 7上,用于串行,并行和CMS垃圾收集器,但不适用于G1 GC。