0%

java | wait && notify

如果一个线程加锁后,但是,资源一直迟迟不来,就会一直加锁。

这个时候,进行 wait 就会进入到 waitset 变为 waiting 状态。

等有资源后,通过 notify 或者 notifyAll 唤醒,然后进入 EntryList 重新竞争。

waiting 是已经获得了锁,但是调用 wait 后的状态。

API

  • obj.wait()
    • 让进入 object 监视器的线程到 waitset 等待
    • wait 里面可以传递参数,这里不再详细说明
  • obj.notify()
    • object 上正在 waitset 等待的线程挑一个唤醒
  • obj.notifyAll()
    • object 上正在 waitset 等待的线程全部唤醒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package com.redisc;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.openjdk.jol.info.ClassLayout;

import java.util.concurrent.TimeUnit;

@Data
class User {
}

@Slf4j(topic = "c.Test")
public class Test {
static final Object lock = new Object(); // 加上 final 保证锁的引用不替换

public static void main(String[] args) throws Exception {
new Thread(() -> {
synchronized (lock) {
log.debug("执行");
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "t1").start();

new Thread(() -> {
synchronized (lock) {
log.debug("执行...");
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();

log.debug("其他代码");
synchronized (lock) {
log.debug("唤醒一个随机线程");
lock.notify();
// lock.notifyAll(); // 唤醒全部
}
}

}

输出

1
2
3
4
22:32:05.534 [t1] DEBUG c.Test - 执行
22:32:05.534 [main] DEBUG c.Test - 其他代码
22:32:05.536 [Thread-0] DEBUG c.Test - 执行...
22:32:05.536 [main] DEBUG c.Test - 唤醒一个随机线程

sleep 和 wait 的区别

  • sleepThread 方法,waitObject 的方法
  • sleep 不需要强制和 synchronized 配合使用,但是 wait 需要和 synchronized 一起用
  • sleep 在睡眠的同时,不会释放对象锁,但是,wait 在等待的时候会释放对象锁
请我喝杯咖啡吧~