为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕田峪7331174 2023-03-31 09:14:02
考虑以下代码:Thread A:closed = true; // closed is a volatile variableclose();Thread B:while(true){  if(!closed){    write();  }  else {    ...  }}如果我没理解错的话,closed = true;happens-beforeclose();和closed = true;happens-before ,但是和write();之间好像没有 happens-before 关系。close();write();上面的代码是否确保write();只会在之前被调用close()?如果没有,可以进行哪些修改以使其工作?还是我必须使用synchronized?
查看完整描述

3 回答

?
米琪卡哇伊

TA贡献1998条经验 获得超6个赞

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

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

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

有问题的情况:

线程 B可能在线程 A翻转write()并继续执行的过程中。closed = trueclose()

通过保护整个执行来使用显式锁定write(),并使用相同的锁来确保您close()在写入时不会调用。


查看完整回答
反对 回复 2023-03-31
?
翻阅古今

TA贡献1780条经验 获得超5个赞

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



查看完整回答
反对 回复 2023-03-31
?
繁星点点滴滴

TA贡献1803条经验 获得超3个赞

基本上你在这里需要的是一个命令,即writestatement executed before close()

  1. Volatile 无济于事,因为它只是将变量直接写入内存。close()它对声明没有任何规定

  2. 同步关键字只是防止另一个线程进入另一个/同一个同步块,在同一个监视器上同步。如果两个任务都必须由不同的线程完成,则再次不适合订购。

在 Kotlin 中解决这个问题的一个非常简单的例子(java 将是类似的)。您创建一个可用于锁定的对象。

  1. 您的关闭线程A将等待获取 Object 的锁lock

  2. 另一个线程B不会等待获得锁。相反,它将关闭并通知所有线程完成它们的工作。

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


请注意,此方法存在很大缺陷,是让您步入正轨的基本示例。您可能想要使用可重入锁,并在您的完整代码中仔细考虑。


查看完整回答
反对 回复 2023-03-31
  • 3 回答
  • 0 关注
  • 129 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信