在线程之间传递可变数据

pyt*_*ude 16 java concurrency multithreading

这是关于Java中多线程的一个基本问题:我有一个非常大的可变数据结构(确切地说是一棵树)我明白如果我想从两个不同的线程同时修改这个数据结构,我需要使用锁和/或其他类型的线程安全.

然而,在我的情况下,两个线程不需要修改数据结构的同时,相反,通常拥有数据结构的线程A应该暂时将后者传递给线程B,并且线程B应该在对它进行一些长时间运行的修改之后将数据结构传递回线程A.

如果保证线程不会同时修改数据,那么在线程之间来回传递这个可变数据结构是否是线程安全的?

Ale*_*ler 12

如果你可以保证线程不会同时修改树(即通过原子方式传递对树的唯一引用),从线程安全的角度来看就没问题了.

但是,数据可见性/一致性是另一个问题.除非(递归地)声明树中的所有字段,否则volatile一个线程所做的更改可能不会对另一个线程可见.要避免,请确保在线程交换树的所有权时获取监视器(充当内存屏障并确保所有写入变为可见).

  • 其他答案在这里更准确:你只需要建立A'拥有'树和B'拥有树'之间的"发生前"关系 - 你怎么做也没关系.但是,在更改所有权时获取监视器(即输入`synchronized`块)是一种直接的方法.如果之后,它不需要保持,它只用于在交换点建立内存屏障. (4认同)

NPE*_*NPE 9

是的,只要您在线程之间传递对象时采取特定步骤来避免内存一致性错误,您所描述的内容就可以正常工作.使用锁定是实现这一目标的一种方法,但还有其他方法 - 更便宜.

教程是一个很好的起点.

基本上,您需要确保当线程A将对象传递给线程B时,A 发生的所有更改都会 B访问对象之前发生.

JLS还有更多,但它相当技术性.


use*_*740 5

如果没有进一步的同步保证,这不是线程安全的。

基本上,如果没有适当的同步,就无法确保线程之间的可见性一致——例如synchronized,JLS 的 , 或其他发生在之前的保证。也就是说,即使可能没有“并发修改”,也不能保证非编写器线程看到对所述对象的修改。