我编写多线程软件,但我对Java有些不理解。
我的理解是Java对象共享内存地址空间。因此,任意数量的线程都可以看到和访问任意数量的对象。
如果我在主线程中创建线程,并将构造函数中的一个对象传递给每个线程,Java解释器就不会在线程之间进行编组。
Java如何执行Java程序的内存模型是线程安全的,并且不会看到部分对象的构造?
换句话说,如果程序的构造函数正在运行,那么在创建对象时,什么可以阻止内存模型无效?当然,我承认没有人可以引用正在构造的对象。但是Java的簿记保存必须将对象存储在内存中,这需要线程安全。
发布于 2022-11-10 20:48:18
我的理解是Java共享一个内存地址空间。因此,任意数量的线程都可以看到和访问任意数量的对象。
是的,他们可以看到正确分配和构造的对象,他们有一个引用。Java线程不能在没有引用的情况下随机地从堆内存中获取对象。通过线程安全的设计,低级别的JVM内部没有.
如果我在主线程中创建线程并将构造函数中的一个对象传递给每个线程,那么
解释器不会在线程之间进行编组。
是的,在Java语言级别,您可以使用leak this in the constructor。这是一种特殊的方式来射击自己的脚,反过来,你可以避免通过泄漏对象引用,直到对象准备好,自己的脚射击。
正如Basil Bourque在评论中指出的那样,这是为什么构造函数通常应该简短和简单的另一个因素,而复杂初始化可以从使用构建器模式中获益。
如何确保Java程序的内存模型是线程安全的,并且不会看到部分对象的构造?
低级堆管理机器是线程安全的,因为它以线程安全的方式分配堆内存块,垃圾以线程安全的方式收集它们。考虑大约同时从两个线程执行以下构造函数调用:
someclass x = new someclass();0 new #1 // Class [someclass]
3 dup
4 invokespecial #4 // Method [someclass].<init>()V
7 areturn两个线程分别执行字节码new并获得未初始化的对象。因为低级别的堆分配机制是线程安全的,所以这两个线程得到不同的对象.它们位于共享内存空间的事实与此无关--它们仍然是独立的对象。
它们调用构造函数来初始化它们各自的对象--这仍然很好。对象引用仅以两种方式提供给java代码--或者在构造函数返回后分配给x,或者如果您有意在构造函数中泄漏引用。即使您确实泄漏了对对象的Java引用,对象头部的实际低级别分配和初始化也基本上已经完成-- new字节码已经运行完毕。
,但是Java的簿记保存必须将对象存储在内存中,这需要线程安全。
是的,而且确实如此。分配程序是线程安全的,GC是线程安全的,几乎所有其他低级对象访问都是响应您的Java代码使用它拥有的引用对对象进行操作的。
完全并发的GC/分配器可以是符合规范的JVM的一部分。单线程/停止世界GC/分配器可以是符合规范的JVM的一部分(但是JVM的性能扩展可能很差)。当两个线程同时创建对象时,破坏堆的分配器就会被破坏,构建在上面的JVM就会中断。
https://stackoverflow.com/questions/74394887
复制相似问题