Java 我是否需要在读写器场景中使这两个变量都不稳定?

Java 我是否需要在读写器场景中使这两个变量都不稳定?,java,concurrency,concurrent-programming,Java,Concurrency,Concurrent Programming,我们有两条线。一个是读者。另一个是共享以下两个变量的编写器线程: Object data boolean ready 我是否需要使两者都不稳定?是否足以使“就绪”不稳定 write() { data = <some data> ready = true; } read() { if (ready) { consume(data); ready = false; } } write(){ 数据= 就绪=正确; }

我们有两条线。一个是读者。另一个是共享以下两个变量的编写器线程:

Object data
boolean ready
我是否需要使两者都不稳定?是否足以使“就绪”不稳定

write() {
    data = <some data>
    ready = true;
}

read() {
    if (ready) {
        consume(data);
        ready = false;
    } 
}
write(){
数据=
就绪=正确;
}
读(){
如果(准备就绪){
消费(数据);
就绪=错误;
} 
}
我是否需要使这两个变量都不稳定

write() {
    data = <some data>
    ready = true;
}

read() {
    if (ready) {
        consume(data);
        ready = false;
    } 
}
基于我对java内存模型的有限理解,我认为我只需要将'ready'设置为volatile,因为读/写'ready'之前的所有代码都发生在读/写'ready'变量之后的代码之前


更新:就本问题而言,假设原子性不是一个问题。数据的产生和消耗是原子性的。

挥发物在使用时有利于发出信号,但不利于原子性。您需要原子性,以防数据在使用时得到更新,但尚未设置就绪

你的问题与另一个问题类似


正如我在那里所说的,如果数据和就绪仅由一个线程更新,那么volatile对两个都可以正常工作。Atomic适用于多个作者。

您的理解是正确的

当线程1写入一个易失性变量,然后线程2读取该易失性变量时,在易失性写入之前线程1可见的所有变量在易失性读取之后变为线程2可见。就像线程1离开同步块,然后线程2进入一样


但这不是提供可见性的推荐方法,因为它不像进入/退出同步块或获取/释放锁那样显式地显示自己

正如其他关于原子性的人所说,您可以通过使用ReadWriteLock来提高并发性。详情请浏览:


在这种情况下,可能会有多个读卡器线程,并且写锁是独占的。

在您的示例中,Volatile变量对于状态标志(如ready)很方便,但只保证以线程安全的方式访问值,不保证按顺序执行其余块

在您的示例中,写入(数据)读取()操作可以并行执行,消耗(数据)的执行时间可能导致读取()在第二次调用写入(数据)后完成这将导致将就绪变量设置为false,即使通过第二次调用写入(数据)设置的新数据预期为true

例如:

线程1开始:写入(数据1)

线程1 end://ready:true,data=data1

线程2启动:read()//消费(数据1)需要一段时间

线程3启动:写入(数据2)//就绪=true,数据=data2


线程2结束:read()//消费(data2)完成,ready=false,data=data2

原子性如何:消费数据时,它会再次更新?