wait/notify底层
- Owner 线程发现条件不满足,调用 wait 方法,即可进入 WaitSet 变为 WAITING 状态
- BLOCKED 和 WAITING 的线程都处于阻塞状态,不占用 CPU 时间片
- BLOCKED 线程会在 Owner 线程释放锁时唤醒
- WAITING 线程会在 Owner 线程调用 notify 或 notifyAll 时唤醒,但唤醒后并不意味者立刻获得锁,仍需进入
- EntryList 重新竞争
相关API
- obj.wait() 让进入 object 监视器的线程到 waitSet 等待
- obj.notify() 在 object 上正在 waitSet 等待的线程中挑一个唤醒
- obj.notifyAll() 让 object 上正在 waitSet 等待的线程全部唤醒
方法都是Object里面的方法,必须获得此对象锁,才能调用这几个方法。方法操作目标是线程本身。
public class Test02 {
final static Object obj = new Object();
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
synchronized (obj) {
System.out.println("执行" + Thread.currentThread());
try {
obj.wait(); // 让线程在obj上一直等待下去
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("完毕" + Thread.currentThread());
}
}, "t1").start();
new Thread(() -> {
synchronized (obj) {
System.out.println("执行" + Thread.currentThread());
try {
obj.wait(); // 让线程在obj上一直等待下去
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("完毕" + Thread.currentThread());
}
}, "t2").start();
// 主线程两秒后执行
sleep(2);
System.out.println("唤醒 obj 上其它线程");
synchronized (obj) {
obj.notify(); // 唤醒obj上一个线程
// obj.notifyAll(); // 唤醒obj上所有等待线程
}
}
}
sleep(long n)和wait(long n)区别
- sleep 是 Thread 方法,而 wait 是 Object 的方法
- sleep 不需要强制和 synchronized 配合使用,但 wait 需要和 synchronized 一起用
- sleep 在睡眠的同时,不会释放对象锁的,但 wait 在等待的时候会释放对象锁
虚假唤醒
就是一个线程调用了notify后,唤醒了条件还是不满足的线程,可以用notifyAll方法解决一部分问题