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()