一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情。
park,unpark
基本使用
它们是 LockSupport 类中的方法
// 暂停当前线程
LockSupport.park();
// 恢复某个线程的运行
LockSupport.unpark(暂停线程对象)
先 park 再 unpark
先 unpark 再 park
原理
每个线程都有自己的一个 Parker 对象,由三部分组成 _counter , _cond 和 _mutex 打个比喻
-
线程就像一个旅人,Parker 就像他随身携带的背包,条件变量就好比背包中的帐篷。_counter 就好比背包中的备用干粮(0 为耗尽,1 为充足)
-
调用 park 就是要看需不需要停下来歇息
-
如果备用干粮耗尽,那么钻进帐篷歇息
-
如果备用干粮充足,那么不需停留,继续前进
-
-
调用 unpark,就好比令干粮充足
-
如果这时线程还在帐篷,就唤醒让他继续前进
-
如果这时线程还在运行,那么下次他调用 park 时,仅是消耗掉备用干粮,不需停留继续前进
-
因为背包空间有限,多次调用 unpark 仅会补充一份备用干粮
-
-
-
当前线程调用 Unsafe.park() 方法
-
检查 _counter ,本情况为 0,这时,获得 _mutex 互斥锁
-
线程进入 _cond 条件变量阻塞
-
设置 _counter = 0
-
调用 Unsafe.unpark(Thread_0) 方法,设置 _counter 为 1
-
唤醒 _cond 条件变量中的 Thread_0
-
Thread_0 恢复运行
-
设置 _counter 为 0
-
调用 Unsafe.unpark(Thread_0) 方法,设置 _counter 为 1
-
当前线程调用 Unsafe.park() 方法
-
检查 _counter ,本情况为 1,这时线程无需阻塞,继续运行
-
设置 _counter 为 0
线程状态切换
假设有线程 Thread t
情况 1 NEW --> RUNNABLE
- 当调用
t.start()方法时,由NEW --> RUNNABLE
情况 2 RUNNABLE <--> WAITING
t 线程用 synchronized(obj) 获取了对象锁后
-
调用
obj.wait()方法时,t 线程从RUNNABLE --> WAITING -
调用
obj.notify(),obj.notifyAll(),t.interrupt()时-
竞争锁成功,t 线程从
WAITING --> RUNNABLE -
竞争锁失败,t 线程从
WAITING --> BLOCKED
-
情况 3 RUNNABLE <--> WAITING
-
当前线程调用
t.join()方法时,当前线程从RUNNABLE --> WAITING- 注意是当前线程在t 线程对象的监视器上等待
-
t 线程运行结束,或调用了当前线程的 interrupt() 时,当前线程从
WAITING --> RUNNABLE
情况 4 RUNNABLE <--> WAITING
-
当前线程调用 LockSupport.park() 方法会让当前线程从
RUNNABLE --> WAITING -
调用 LockSupport.unpark(目标线程) 或调用了线程 的 interrupt() ,会让目标线程从
WAITING -->RUNNABLE
情况 5 RUNNABLE <--> TIMED_WAITING
t 线程用 synchronized(obj) 获取了对象锁后
-
调用 obj.wait(long n) 方法时,t 线程从
RUNNABLE --> TIMED_WAITING -
t 线程等待时间超过了 n 毫秒,或调用
obj.notify(),obj.notifyAll(),t.interrupt()时-
竞争锁成功,t 线程从
TIMED_WAITING --> RUNNABLE -
竞争锁失败,t 线程从
TIMED_WAITING --> BLOCKED
-
情况 6 RUNNABLE <--> TIMED_WAITING
-
当前线程调用 t.join(long n) 方法时,当前线程从 RUNNABLE --> TIMED_WAITING
- 注意是当前线程在t 线程对象的监视器上等待
-
当前线程等待时间超过了 n 毫秒,或t 线程运行结束,或调用了当前线程的
interrupt()时,当前线程从TIMED_WAITING --> RUNNABLE
情况 7 RUNNABLE <--> TIMED_WAITING
-
当前线程调用
Thread.sleep(long n),当前线程从RUNNABLE --> TIMED_WAITING -
当前线程等待时间超过了 n 毫秒,当前线程从
TIMED_WAITING --> RUNNABLE
情况 8 RUNNABLE <--> TIMED_WAITING
-
当前线程调用
LockSupport.parkNanos(long nanos)或LockSupport.parkUntil(long millis)时,当前线程从RUNNABLE --> TIMED_WAITING -
调用
LockSupport.unpark(目标线程)或调用了线程 的interrupt(),或是等待超时,会让目标线程从TIMED_WAITING--> RUNNABLE
情况 9 RUNNABLE <--> BLOCKED
-
t 线程用
synchronized(obj)获取了对象锁时如果竞争失败,从RUNNABLE --> BLOCKED -
持 obj 锁线程的同步代码块执行完毕,会唤醒该对象上所有
BLOCKED的线程重新竞争,如果其中 t 线程竞争成功,从BLOCKED --> RUNNABLE,其它失败的线程仍然BLOCKED
情况 10 RUNNABLE <--> TERMINATED
当前线程所有代码运行完毕,进入 TERMINATED