如果我访问同步方法或同步块内的对象,那个被访问元素中的所有对象是否也同步?
想象一下,对象Queue
具有同步add()
和take()
方法,接受并分发复杂对象Thing
。 Thing
包含许多包含其他不同对象的列表。
现在图像线程Before
创建Thing
并将一些现有对象放入Thing
,修改其中一些对象,依此类推。 Before
主题将Thing
添加到Queue
。稍后的线程After
从Thing
获取Queue
。
问题:Thing
及其所有子/子对象是否与Before
处于同一状态?即使线程After
可能稍早在这些子元素之一上工作?因为我对线程After
的处理器进行映像可能仍然有一些关于该子元素的缓存信息(该子对象的地址仍然相同)。只有通过同步方式访问父对象Thing
,所有这些缓存的东西才会失效?
请不要给出使用并发库等的答案。我想了解发生了什么。
答案 0 :(得分:9)
如果一个线程修改了一个变量,那么另一个线程不能保证看到更改,除非在下列情况下(好吧,至少在以下情况下;我不是100%确定是否有更多):
volatile
,或者它是来自java.util.concurrent.atomic
因此,如果您按照说明进行同步,其他线程将看到所有更改。
答案 1 :(得分:7)
Java的内存模型中的重要概念是happens-before order。 发生在读取操作之前的写入操作的结果对于这些读取操作是可见的。其他结果可能会也可能不会显示。
发生在之前的顺序是由线程之间的操作的同步顺序以及各个线程中的自然操作顺序引起的。
如果您在Before
同步对象(例如您的Queue
),并在此同步块内或之前对Thing
及其“子对象”进行所有操作,并且After
在同一个Queue
上同步并在同步块中或之后读取这些对象,然后所有这些更改对After
可见。