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 类的方法。

相关内容

热门资讯

重大通报作弊器!乐乐上海麻将a... 重大通报作弊器!乐乐上海麻将ai智能透视辅助插件,乐乐上海麻将本来存在有外挂(有辅助挂方略)1、很好...
分享给玩家透视挂!家乡大贰ai... 分享给玩家透视挂!家乡大贰ai智能透视辅助工具,家乡大贰其实真的有外挂(有辅助挂细节)家乡大贰破解侠...
科普攻略开挂!英豪娱乐城ai智... 科普攻略开挂!英豪娱乐城ai智能透视辅助教程,英豪娱乐城好像真的是有外挂(有辅助挂头条)1、英豪娱乐...
总算了解辅助器!和悦游戏ai智... 总算了解辅助器!和悦游戏ai智能透视辅助教程,和悦游戏确实是真的有外挂(竟然有辅助挂)暗藏猫腻,小编...
揭秘关于辅助器!九九麻将ai智... 揭秘关于辅助器!九九麻将ai智能透视辅助技巧,九九麻将一贯是有外挂(有辅助挂方略)1、用户打开应用后...