Rx java 如果在反应lambda构造之间传递有状态对象,您需要关心线程可见性吗?

Rx java 如果在反应lambda构造之间传递有状态对象,您需要关心线程可见性吗?,rx-java,rx-java2,reactor,Rx Java,Rx Java2,Reactor,假设我们使用的是RxJava或Reactor,我们有一个对象,它包含两个属性,可以通过setter进行变异。假设我们在不同的线程池上运行一些操作。我们在管道中多次使用此状态对象并更改其属性。我们是否仍然需要“volatile”来确保缓存的版本不会返回?或者有一种机制和管道的顺序性一起确保修改后的对象通过flatMap返回,例如?在每次修改时,我们需要让这个对象不可变并重新创建吗?< p>在修改多个流水线中的单个对象的情况下,考虑以下内容: //这个例子在Kotlin中,但对java来说应该是相当

假设我们使用的是RxJava或Reactor,我们有一个对象,它包含两个属性,可以通过setter进行变异。假设我们在不同的线程池上运行一些操作。我们在管道中多次使用此状态对象并更改其属性。我们是否仍然需要“volatile”来确保缓存的版本不会返回?或者有一种机制和管道的顺序性一起确保修改后的对象通过flatMap返回,例如?在每次修改时,我们需要让这个对象不可变并重新创建吗?

< p>在修改多个流水线中的单个对象的情况下,考虑以下内容:

//这个例子在Kotlin中,但对java来说应该是相当容易分析的
主要内容(){
变量计数=0
流动范围(0,1000)
//将流拆分为“平行管道”
.parallel()
.runOn(Schedulers.computation())
.doAfterNext{count+=1}
//合并回单个管道

.subscribe()
println(计数)
}
此操作的结果会有所不同,但在我的计算机上,它会打印
600
-
850

在本例中,我们有两种方法可以解决这个问题,即使用
AtomicInteger
代替使用的
Int
。更好的做法是不存储任何计数变量,只需在每个并行进程上执行加法,然后在返回到一个流后使用
sequential
组合结果,但我不确定这是否适用于您的问题


总而言之,如果要修改任意数量的对象,但一次只能在一个管道中修改,则不必担心线程问题,因为修改仅限于一个线程。如果它同时被分割成多个管道,那么您就必须像处理任何多线程应用程序一样担心这个问题。解决方案可能涉及使用Java中可用的锁或同步对象,或者可能有一种更被动的方式来避免这些问题(比如一次只在一个管道中处理),但是,如果没有一个具体的例子,很难说。

每当您有从不同线程读取和写入的状态时,您需要使用其中一种同步机制来确保线程“看到”其他线程操作的效果

如果没有适当的同步,线程可能会看到部分效果或以意外顺序出现的效果

有关更多详细信息,请参阅


因此,您应该确保对状态对象的所有访问都正确同步。或者,您可以避免在管道中修改状态。改用不可变的数据结构

是否有多个“管道”正在修改此对象?“还是该对象只在一条管道中使用?”威廉姆里德(WilliamReed)抱歉,最终在你的回答下回答。对象用于单个长非并行管道,一些任务被分派到不同的tps。对象在被分派到另一个tp进行另一个阶段的处理之前,可以在每个阶段中修改。希望这是有意义的:-p我仍然不知道发生了什么的关键部分是当您有一个管道时,但是您将管道上下文切换到另一个线程,从要完成的工作的角度来看,这不是平行的,因为只有一个线程在管道的一部分上工作。所以线程必须传递上下文,它们不共享上下文,这是一个步骤转换,我不确定在这种情况下会发生什么。因此,如果我们以您的示例为例,删除.parallel并添加更多计算以及线程切换。或者我可以自己试试:-P@Aubergine如果在单个管道中使用
observeOn
切换线程,我们每次只能在单个线程中修改它。您可能不必担心竞争条件,但是标记使用中的变量
volatile
可能很有用。我不确定rxjava是否在如何传递对象的问题上做了什么,因此可能根本不需要它。但一定要在一个简单的例子中尝试一下