Java的同步会更新完整的缓存,还是只更新我同步的对象?

时间:2011-08-28 10:44:01

标签: java concurrency synchronization parallel-processing monitor

如果我访问同步方法或同步块内的对象,那个被访问元素中的所有对象是否也同步?

想象一下,对象Queue具有同步add()take()方法,接受并分发复杂对象ThingThing包含许多包含其他不同对象的列表。

现在图像线程Before创建Thing并将一些现有对象放入Thing,修改其中一些对象,依此类推。 Before主题将Thing添加到Queue。稍后的线程AfterThing获取Queue

问题:Thing及其所有子/子对象是否与Before处于同一状态?即使线程After可能稍早在这些子元素之一上工作?因为我对线程After的处理器进行映像可能仍然有一些关于该子元素的缓存信息(该子对象的地址仍然相同)。只有通过同步方式访问父对象Thing,所有这些缓存的东西才会失效?

请不要给出使用并发库等的答案。我想了解发生了什么。

2 个答案:

答案 0 :(得分:9)

如果一个线程修改了一个变量,那么另一个线程不能保证看到更改,除非在下列情况下(好吧,至少在以下情况下;我不是100%确定是否有更多):

  • 修改线程离开同步块或方法;这会引起线程缓存的刷新(同样是进入同步块或方法的线程引起刷新) - 这就是你的情况下发生的事情
  • 修改后的变量声明为volatile,或者它是来自java.util.concurrent.atomic
  • 的原子变量之一
  • 修改线程完成(这也会导致刷新,同样线程的开始会导致刷新)

因此,如果您按照说明进行同步,其他线程将看到所有更改。

答案 1 :(得分:7)

Java的内存模型中的重要概念是happens-before order发生在读取操作之前的写入操作的结果对于这些读取操作是可见的。其他结果可能会也可能不会显示。

发生在之前的顺序是由线程之间的操作的同步顺序以及各个线程中的自然操作顺序引起的。

如果您在Before同步对象(例如您的Queue),并在此同步块内或之前对Thing及其“子对象”进行所有操作,并且After在同一个Queue上同步并在同步块中或之后读取这些对象,然后所有这些更改After可见。