【多线程】多线程(6):等待和通知

【wait与notify(等待与通知)】

线程在操作系统上的调度是随机的

多个线程中,需要控制线程之间执行某个逻辑的先后顺序,就可以让后执行的逻辑,在一个线程内使用锁对象去调用wait,可以让这个线程进入阻塞,待其他线程完成某些逻辑之后,通过锁对象调用notify就可以唤醒对应的wait

//设锁为locker
locker.wait();

locker.notify();

wait和notify都是Object提供的方法,因此任意的Object对象都可以用来调用wait和notify

通过wait和notify也可以解决「线程饿死」问题

//wait中会进行一个操作:针对Object对象先进行解锁,所以使用wait,务必要放到“synchronized”代码块中

必须先加上锁,才能谈“解锁”

【线程饿死】

A线程加锁想执行操作,但里面没有资源,于是执行失败,释放锁后离去

但A线程转过头来不信邪,再次加锁进去,还是没有,失败,释放锁后离去

如此反复循环,导致后面的一系列线程无法执行

【解决:线程饿死问题】

让A线程拿到锁时进行判定

判定当前能否执行操作,如果能,就正常执行

如果不能,就需要主动释放锁,并且「阻塞等待」(通过调用wait),此时这个线程不会在后续参与锁的竞争了

一直阻塞到,A线程“执行操作”的条件具备了,此时,再由其他线程通过「通知机制」(notify)唤醒这个线程

★wait做的事

1.释放锁

2.进入阻塞等待,准备接受通知

3.收到通知后,唤醒,并重新尝试获取锁

//调用wait的锁对象和加锁的对象必须是同一个锁对象,若不同,则操作失败

synchronized (locker){
            System.out.println("A");
            locker.wait();//和synchronized的锁对象必须相同
        }

//wait括号中还可以指定参数,用于指定超时时间,若wait达到时间还没有notify,就不会继续等待,而是直接继续执行

【注意事项】

wait使调用的线程进入阻塞

notify则是通知wait的线程被唤醒(由另一个线程调用)

被唤醒的wait会重新竞争锁,并且在拿到锁后再继续执行

【notify的补充】

假设多个线程,若多个线程都在同一个锁对象上wait,此时notify会随机唤醒其中一个线程

【notifyAll】

唤醒所有等待的线程

synchronized (locker){
            locker.notifyAll();
        }

//这里锁对象为locker,因此可以唤醒所有锁对象为locker且处于wait状态的线程

但需要知道的是,一个一个唤醒(多执行几次notify),整个程序执行过程是比较有序的

若一下唤醒所有,这些被唤醒的线程,就无序的竞争锁

【wait和sleep的区别】

1.使用wait的目的是为了提前唤醒

使用sleep的目的是为了固定时间的阻塞,不涉及唤醒(虽然sleep可以被interrupt唤醒,但这表示的意思不是“唤醒”,而是要终止线程了)

2.wait必须搭配synchronized使用,且wait会先释放锁,同时进行等待

sleep和锁无关,若不加锁,sleep可以正常使用,若加了锁,sleep不会释放锁,而是会“抱着锁”一起睡,致使其他线程无法拿到锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值