JAVA多线程番外篇 2、while和wait的配合使用

理解了多线程,才能理解了现代分时操作系统,并进一步理解更多系统应用组件的底层原理。并发编程是低级程序员跨越到中高级程序员必过一关,是区分程序员水平的最常用的标准。在程序员求职过程中,多线程知识会被频繁问及考察,几乎所有的招聘要求里都会要求熟悉高并发编程。

1.wait需要配合while使用

在线程协调的场景中,常常会看到wait和while配合使用。

比如一个消费者,在判定队列是否为空,使用如下代码:

为什么需要使用到while呢?

public void synchronized consume() {
    while(队列==) {
        wait();
    }
    消费();
    notifyAll();
}

2.机制原理

我们逐行分析代码,

  • 首先这是一个同步方法。synchronized意味着,方法在执行过程中会通过锁定this,实现互斥原子性操作。

  • 此时,如果队列==空,那么意味着消费者线程需要等待,那么就会执行wait()方法。

  • wait()方法执行后,就会释放锁,并将当前线程放进等待队列中。

2.1 为什么需要再次判定

  • 如果有两个生产者A和B,一个消费者C。当存储空间满了之后,生产者A和B都被wait,进入等待唤醒队列。当消费者C取走了一个数据后,如果调用了notifyAll(),则生产者线程A和B都将被唤醒,如果此时A和B中的wait不在while循环中而是在if中,**则A和B就不会再次判断是否符合执行条件,**都将直接执行wait()之后的程序,那么如果A放入了一个数据至存储空间,则此时存储空间已经满了;但是B还是会继续往存储空间里放数据,错误便产生了。
  • 如果有两个生产者A和B,一个消费者C。当存储空间满了之后,生产者A和B都被wait,进入等待唤醒队列。当消费者C取走了一个数据后,如果调用了notify(),则A和B中的一个将被唤醒,假设A被唤醒,则A向存储空间放入了一个数据,至此空间就满了。**A执行了notify()之后,如果唤醒了B,**那么B不会再次判断是否符合执行条件,将直接执行wait()之后的程序,这样就导致向已经满了数据存储区中再次放入数据。

2.2 为什么需要使用while呢,能不能使用if 判断呢?

  • 如果使用if
    • 当这个沉睡的线程被唤醒时,它醒来的地方就会直接进入下一个指令消费()。而不会在此判断。
  • 如果使用while
    • 当这个沉睡的线程被唤醒时,它醒来的地方还在循环内。于是会进行再一次判定,队列是否为空。
    • 如果队列为空就会继续wait()
    • 如果队列不为空才会执行消费()

总结

记住,在多线程开发模式里需要注意安排wait和while的搭档,他们两个能够形成一个安全屏障,让不该醒来却醒来的线程再次睡去。

多线程系列在github上有一个开源项目,主要是本系列博客的实验代码。

https://github.com/forestnlp/concurrentlab

如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。

您的支持是对我最大的鼓励。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值