栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

线程状态模型与synchronized的wait与notify方法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程状态模型与synchronized的wait与notify方法

1. 线程状态图


这是线程的7状态模型图,常见的7大状态之间的转换关系也在上面。多线程之间的通信主要用到4个方法,wait()、wait(long time)、notify()、notifyAll(),其他方法在多线程基础中都有介绍。

1. wait():作用是使当前线程从调用处中断并且释放锁转入等待队列,直到收到notify或者notifyAll的通知才能从等待队列转入锁池队列,没有收到停止会一直死等。

2. wait(long time):相比wait多了一个等待的时间time,如果经过time(毫秒)时间后没有收到notify或者notifyAll的通知,自动从等待队列转入锁池队列。

3. notify():随机从等待队列中通知一个持有相同锁的一个线程,如果没有持有相同锁的wait线程那么指令忽略无效。注意是持有相同锁,并且是随机没有固定的,顺序这一点在生产者消费者模型中很重要,会造成假死的状态。

4. notifyAll():通知等待队列中的持有相同锁的所有线程,让这些线程转入锁池队列。如果没有持有相同锁的wait线程那么指令忽略无效。

5. wait的两个方法都需要注意中断的问题,wait中断是从语句处中断并且释放锁,当再次获得锁时(在锁池队列中)是从中断处继续向下执行。

6. 在while循环里而不是if语句下使用wait,这样,会在线程暂停恢复后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知

7. notify 和 notifyAll方法通知是延迟通知,必须等待当前线程体执行完所有的同步方法/代码块中的语句退出释放锁才通知wait线程。

8. 这四个方法都必须在获得锁的情况下才能调用,否则会出现非法监视状态异常。

2.永远在循环(loop)里调用 wait 和 notify,不是在 If 语句

        我们现在已经知道了wait()应该永远在被synchronized同步代码块或同步方法中进行调用,而需要着重注意的一点是:应该永远在while循环,而不是if语句中调用wait。

为线程是在某些条件下等待的————我们在实际开发中往往会设定一些条件,而使线程进入等待,这个时候你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,但是你的线程你也有可能被错误地唤醒,此时使用if会使线程在没有满足条件的情况下向下执行。所以如果你不在线程被唤醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错。

所以,根据JDK给出的代码示例,应该这样去使用wait():

synchronized (obj) {
    while ()
        obj.wait();
        // Perform action appropriate to condition
        // Do something......
}

在while循环里使用wait的目的,是在线程被唤醒的前后都持续检查条件是否被满足。如果条件并未改变,wait被调用之前notify的唤醒通知就来了,那么这个线程并不能保证被唤醒,有可能会导致死锁问题。
 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/847264.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号