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

考虑以下代码:


Thread A:

closed = true; // closed is a volatile variable

close();


Thread B:

while(true){

  if(!closed){

    write();

  }

  else {

    ...

  }

}


如果我没理解错的话,closed = true;happens-beforeclose();和closed = true;happens-before ,但是和write();之间好像没有 happens-before 关系。close();write();


上面的代码是否确保write();只会在之前被调用close()?如果没有,可以进行哪些修改以使其工作?还是我必须使用synchronized?


慕田峪7331174
浏览 134回答 3
3回答

米琪卡哇伊

你不能保证close() 之前发生 write()。你有volatile closed各种各样的信号量。你可以用它来发出事件信号,但你不应该用它来保证互斥。在您的情况下,线程 A可以向线程 B发出信号(A 正在写入,B 从volatile变量读取)但线程 A无法从线程 B接收信号,这会导致下面描述的问题情况。volatile仅保证读取将看到最近的写入,但不保证您的写入将在读取之前发生。有问题的情况:线程 B可能在线程 A翻转write()并继续执行的过程中。closed = trueclose()通过保护整个执行来使用显式锁定write(),并使用相同的锁来确保您close()在写入时不会调用。

翻阅古今

你已经给出了答案:“还是我必须使用同步?” 是的!

繁星点点滴滴

基本上你在这里需要的是一个命令,即writestatement executed before close()。Volatile 无济于事,因为它只是将变量直接写入内存。close()它对声明没有任何规定同步关键字只是防止另一个线程进入另一个/同一个同步块,在同一个监视器上同步。如果两个任务都必须由不同的线程完成,则再次不适合订购。在 Kotlin 中解决这个问题的一个非常简单的例子(java 将是类似的)。您创建一个可用于锁定的对象。您的关闭线程A将等待获取 Object 的锁lock另一个线程B不会等待获得锁。相反,它将关闭并通知所有线程完成它们的工作。A 现在可以进入临界区,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()请注意,此方法存在很大缺陷,是让您步入正轨的基本示例。您可能想要使用可重入锁,并在您的完整代码中仔细考虑。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java