我们有两个线程。一个是读者。另一个是共享以下两个变量的编写器线程:
Object data
boolean ready
我需要使两者都不稳定吗?这足以让"现成"变得不稳定吗?
write() {
data = <some data>
ready = true;
}
read() {
if (ready) {
consume(data);
ready = false;
}
}
我需要使这两个变量都不稳定吗?
基于我对java内存模型的有限理解,我认为我只需要让"ready"变得易失性,因为读/写"ready"之前的所有代码都发生在读/写"ready"变量之后的代码之前?
更新:为了这个问题的目的,假设原子性不是一个问题。数据的产生和消耗是原子性的。
挥发物在使用时有利于发出信号,但不利于原子性。您需要原子性,以防数据在消耗时得到更新,但尚未设置就绪。
正如其他人在原子性方面明确指出的那样,您可以通过使用ReadWriteLock来增加并发性。更多详细信息,请访问:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReadWriteLock.html
在这种情况下,可能有多个读取器线程,并且写锁是独占的。
您的问题与SO上的另一个问题类似。
正如我在那里所说,如果数据和就绪仅由一个线程更新,那么volatile对两者都很好。Atomic适用于多个作者。
您的理解是正确的。
当线程1写入一个易失性变量,随后线程2读取该易失性可变变量时,在易失性写入之前线程1可见的所有变量在读易失性之后对线程2可见。就像线程1离开一个同步块,然后线程2进入一样。
但这不是一种推荐的提供可见性的方式,因为它不像进入/退出同步块或获取/释放锁那样明确地显示自己。
在您的示例中,易失性变量对于状态标志(如ready)很方便,但只能保证以线程安全的方式访问值,不能保证其余块按顺序执行。
在您的示例中,write(data)和read()onsump(data第二次调用写入(数据)。
例如:
线程1启动:写入(data1)
线程1结束://就绪:true,data=data1
线程2启动:read()//consume(data1)需要一段时间。
线程3启动:写入(data2)//ready=true,data=data2
线程2结束:read()//consume(data2)finished,ready=false,data=data2