Java 如何使用volatile变量确保关闭操作后不会执行写操作?

Java 如何使用volatile变量确保关闭操作后不会执行写操作?,java,multithreading,Java,Multithreading,考虑以下代码: 线程A: closed=true;//closed是一个易变变量 close(); 线程B: while(true){ 如果(!关闭){ write(); } 否则{ ... } } 如果我理解正确,closed=true发生在close()之前,且关闭=真发生在write()之前,但似乎close()之间没有before关系和write() 上述代码是否确保write()将仅在close()之前被调用。?如果没有,可以做什么修改使其工作?或者我必须使用synchronized

考虑以下代码:

线程A:
closed=true;//closed是一个易变变量
close();
线程B:
while(true){
如果(!关闭){
write();
}
否则{
...
}
}
如果我理解正确,
closed=true发生在
close()之前,且
关闭=真
发生在
write()之前
,但似乎
close()之间没有before关系
write()


上述代码是否确保
write()将仅在
close()之前被调用。
?如果没有,可以做什么修改使其工作?或者我必须使用
synchronized

您已经给出了答案:“或者我必须使用synchronized吗?”是的

这里基本上需要一个命令,即在
close()之前执行
write
语句

  • Volatile没有帮助,因为它只是将变量直接写入内存。它不为
    close()
    语句指定任何内容
  • Synchronized关键字只是防止另一个线程进入另一个/同一个同步块,在同一个监视器上同步。同样,如果两个任务都必须由不同的线程完成,则不适合排序
  • 一个在Kotlin中解决这个问题的非常简单的例子(java将类似)。您可以创建一个可用于锁定的对象

  • 关闭线程
    A
    将等待获取对象上的锁
    lock
  • 另一个线程
    B
    不会等待获得锁。相反,它将关闭并通知所有线程执行其工作
  • A现在可以进入关键区域,
    close()
    ,然后再次释放锁

  • 请注意,此方法存在严重缺陷,是让您走上正轨的一个基本示例。您可能需要使用可重入锁并仔细考虑完整的代码。

    您不能保证
    close()
    发生在
    write()之前

    您有
    volatile closed
    作为各种信号量。你可以用它来表示事件,但不应该用它来保证互斥。在您的情况下,线程A可以向线程B发送信号(A正在写入,B正在从
    volatile
    变量读取),但线程A无法接收到来自线程B的信号,从而导致出现下面描述的问题情况

    volatile
    仅保证读取将看到最近的写入,但不保证写入将发生在读取之前

    有问题的结论是: <强>线程b>强>可以在()/<代码>的中间,而<强>线程A < /强>翻转<代码>关闭= true并继续执行<代码>关闭()< <代码> > < /P> 通过保护
    write()
    的整个执行来使用显式锁定,并使用相同的锁定来确保在写入过程中没有调用
    close()

    您可以按照per的回答在同一对象上同步,或者使用SDK中的来实现这一点

    你需要同步。Volatile没有任何锁定。它只需确保写入在内存中以原子方式进行。同步确保没有其他线程进入线程所在的同一块中。这似乎对这里没有帮助。您必须使用锁定。volatile不能确保以原子方式进行写入。看这里:。如果您将一个变量声明为volatile,这意味着该变量将始终从主内存中读取,而不是缓存。是的,你需要上锁。看看这里:
    close()
    有什么作用?@diginoise在Android HandlerThread上调用
    quit()
    ,我想这与这个问题无关?谢谢你的回答,但你似乎误解了我的问题,我不需要在
    close()
    之前调用
    write()
    ,我只是想确保在
    close()
    之后不会调用
    write()
    ,我已经修改了代码以使其更清晰。@ZumiKua我没有时间编辑我的答案。如果您唯一担心的是阻止在关闭后写入。那么就不需要使用显式锁定。您的假设是正确的,但当close设置为true时,您可能会拒绝某些写入操作,但实际的close()操作尚未发生。只需有两个同步功能。一个用于关闭和设置变量,另一个用于写入。这是更整洁的方式。稍后我将编辑我的答案。
    
    val lock = Object()
    
    val A = Thread{        
       synchronized(lock) {
           lock.wait()
           closed = true; // closed is a volatile variable
           close();
           lock.notifyAll()
       }
    }
    
    val B = Thread{
       synchronized(lock) {
           write()
           lock.notifyAll()
       }
    }
    
    t.start()
    t1.start()
    
    t.join()
    t1.join()