Java:新对象的分配和缓存一致性

use*_*387 1 java multithreading caching

在Java中,假设您有两个线程T1和T2在两个不同的处理器P1和P2上同时运行.

首先,线程T2与obj在(例如)起始存储器位置0x1000处分配的一些对象一起工作.这会导致P2在内部缓存该内存位置的值.T2然后将(仅)对该对象的引用置零,并且它是垃圾收集的.

线程T1然后

    Foo fooRef = new Foo();
    fooRef.x = 10;
Run Code Online (Sandbox Code Playgroud)

它只是发生了fooRef.x位置也是0x1000,因为这个Foo实例被分配重新使用由上面的T2释放的内存.

然后,T1将fooRef引用传递给线程T2(通过队列或其他一些共享内存机制).

T2会从之前看到旧的过时缓存值,还是会看到10的新值?

假设没有硬件缓存一致性机制.当Java为对象解除分配或分配内存时,它本身是否确保清除每个处理器的缓存?(即使存在硬件缓存一致性机制,一致性传播也不是即时的,如果没有采用Java本身的其他一致性度量,T2可能仍然会读取过时值).

Nei*_*fey 5

如果你没有正确同步,那么T2原则上可以看到三件事之一(不一定具有相同的概率):

  • (a)一个明显正确形成的物体,但含有不正确的数据;

  • (b)首先没有正确形成的对象(即不介意你的数据,属于该对象的实际管家元数据不能正确显示,可能导致"坏事发生");

  • (c)意外地,你"躲闪子弹"原样,T2看到物体为T1离开它.

如果你正确地同步(或以另一种方式,正确发布对象),T2将看到对象为T1定义它.在这篇关于final关键字的文章以及与底部链接的其他文章中,我将讨论一些问题和解决方案.其中一些回答了上一个关于什么是对象发布以及为什么需要它的问题?也可以帮忙.

所以,实际上[*]所有的时间,你需要正确同步.如果您没有正确同步,尝试猜测哪些情况(a),(b)或(c)将会发生是危险的.

[*]在有些情况下同步可以,如果你能真正计算出所有可能的"路径",从缺乏同步的,如技术被称为导致可靠地避免非常偶然的先进技术同步捎带在那里你有效地知道,同步将在其他地方"及时"进行.我建议你不要走这条路!