5.玩明白wait-notify-notifyAll方法
创始人
2024-02-12 03:45:19

今天总结一下wait-notify-notifyAll 方法,到底该怎么玩。

1.wait、 notify、 notifyAll

在使用 wait 方法时,必须把 wait 方法写在 synchronized 保护的 while 代码块中,并始终判断执行条件是否满足,如果满足就往下继续执行,如果不满足就执行 wait 方法,而在执行 wait 方法之前,必须先持有对象的 monitor 锁,也就是通常所说的 synchronized 锁。

为什么这么玩呢?

如果不要求 wait 方法放在 synchronized 保护的同步代码中使用,而是可以随意调用,会发生什么呢?

首先会造成线程不安全的情况。这个网站上有很多案例 可以自己去搜索。

所以我们在写代码的时候要这样写:

这样就可以确保 notify 方法永远不会在 buffer.isEmpty 和 wait 方法之间被调用,提升了程序的安全性。

//被 synchronized 保护的同步代码
public void notifyTest(String data) {synchronized (this) {buffer.add(data);notify();}
}
//被 synchronized 保护的同步代码
public String waitTest() throws InterruptedException {synchronized (this) {while (buffer.isEmpty()) {wait();}return buffer.remove();}
}

小知识【虚假唤醒】:

“虚假唤醒”(spurious wakeup)的问题,线程可能在既没有被notify/notifyAll,也没有被中断或者超时的情况下被唤醒。
虽然在实际生产中,虚假唤醒发生的概率很小,但是程序依然需要保证在发生虚假唤醒的时候的正确性,所以就需要采用while循环的结构。
这样即便被虚假唤醒了,也会再次检查while里面的条件,如果不满足条件,就会继续wait,也就消除了虚假唤醒的风险。

2.wait/notify 和 sleep 方法的区别

相同点:

  • 它们都可以让线程阻塞。
  • 它们都可以响应 interrupt 中断:在等待的过程中如果收到中断信号,都可以进行响应,并抛出 InterruptedException 异常。

不同点:

  • wait 方法必须在 synchronized 保护的代码中使用,而 sleep 方法并没有这个要求。
  • 在同步代码中执行 sleep 方法时,并不会释放 monitor 锁,但执行 wait 方法时会主动释放 monitor 锁。
  • sleep 方法中会要求必须定义一个时间,时间到期后会主动恢复,而对于没有参数的 wait 方法而言,意味着永久等待,直到被中断或被唤醒才能恢复,它并不会主动恢复。
  • wait/notify 是 Object 类的方法,而 sleep 是 Thread 类的方法。

相关内容

热门资讯

中信重工申请矿样试验装置相关专... 4月18日消息,国家知识产权局信息显示,中信重工机械股份有限公司申请一项名为“一种定量微细粒矿样柔性...
刺破“开票经济”的数字泡沫 最新发票数据显示,截至3月25日,今年违规招商引资企业较为集中的废弃资源综合利用、再生物资回收等六类...
兰州:筑牢食品药品安全防线 食品药品安全事关百姓身体健康和生命安全。自全省“三抓三促”行动开展以来,兰州市市场监督管理局聚焦食品...
同济等3家公司共同取得爆管侦测... 4月18日消息,国家知识产权局信息显示,同济大学、宁波水表(集团)股份有限公司、浙江宁水水务科技有限...
【聚焦教育家精神巡回宣讲】聆听...   4月16日,贵州省2026年教育家精神巡回宣讲暨“讲述我的育人故事”贵安大学城专场活动在贵州财经...