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