java-doc-park和unpark

park和unpark

线程调用park则等待“许可” unpark方法为指定线程提供“许可(permit)”。

  • 调用unpark之后,再调用park,线程会直接运行
  • 提前调用的unpark不叠加,连续多次调用unpark后,第一次调用park后会拿到“ 许可” 直接运行,后续调用会进入等待
  • 在同步代码块中使用park/unpark,容易出现死锁
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
49
50
import java.util.concurrent.locks.LockSupport;

public class LearnPark {
public static Object iceCream = null;

public static void main(String[] args) throws Exception {
LearnPark par = new LearnPark();
//par.Normal();
par.DeadLock();
}

// 没死锁
public void Normal() throws Exception {
//开启一个线程, 代表小朋友
Thread consumerThread = new Thread(() -> {
if (iceCream == null) { // 若没有冰激凌
System.out.println("没有冰激凌, 小朋友不开心, 等待...");
LockSupport.park();
}
System.out.println("小朋友买到冰激凌, 开心回家");
});
consumerThread.start();
Thread.sleep(3000L); // 3秒之后
iceCream = new Object(); //店员做了一个冰激凌
LockSupport.unpark(consumerThread); //通知小朋友
System.out.println("通知小朋友");
}

// 死锁
// 在同步代码块中使用park/unpark, 容易出现死锁
public void DeadLock() throws Exception {
//开启一个线程, 代表小朋友
Thread consumerThread = new Thread(() -> {
if (iceCream == null) { // 若没有冰激凌
System.out.println("没有冰激凌, 小朋友不开心, 等待...");
synchronized (this) { // 若拿到锁
LockSupport.park(); //执行park
}
}
System.out.println("小朋友买到冰激凌, 开心回家");
});
consumerThread.start();
Thread.sleep(3000L); // 3秒之后
iceCream = new Object(); //店员做了一个冰激凌
synchronized (this) { // 争取到锁以后, 才能恢复consumerThread
LockSupport.unpark(consumerThread);
}
System.out.println("通知小朋友");
}
}