LockSupport.park()
LockSupport.unpark(thread)
它们都是LockSupport类中的方法,基本使用代码如下:
Thread t1 = new Thread(() -> {
log.debug("start...");
sleep(2);
log.debug("park...");
LockSupport.park();
log.debug("resume...");
},"t1");
t1.start();
// 提前unpark会怎样?
sleep(1);
log.debug("unpark...");
LockSupport.unpark(t1);
结果:
19:57:01.248 [t1] DEBUG com.tanjiaming99.TestPark - start...
19:57:02.260 [main] DEBUG com.tanjiaming99.TestPark - unpark...
19:57:03.264 [t1] DEBUG com.tanjiaming99.TestPark - park...
19:57:03.264 [t1] DEBUG com.tanjiaming99.TestPark - resume...
能先unpark再park诶。
park&unpark VS wait¬ify¬ifyAll
- wait, notify, notifyAll必须配合Object Monitor一起使用,而park, unpark不用。
- park, unpark是以线程为单位来【阻塞】和【唤醒】线程,而notify只能随机唤醒一个线程,notifyAll是唤醒所有等待的线程,而不是很【精确】
- (从上面的代码看到)可以先unpark再park,而wait和notify则需要按顺序
原理
每个线程都有自己一个Parker对象,由_couter, _cond, _mutex三部分组成。
- LockSupport.park()
- 当前线程调用park()方法
- 检查_counter,若为0,此时,获得_mutex互斥锁;若为1,线程无需阻塞,继续运行(这是先unpark再park的情况)。
- 线程进入_cond条件变量阻塞
- 设置_counter=0
- LockSupport.unpark()
- 调用unpark(t)方法,设置_counter为1
- 唤醒_cond条件变量中的Thread_0线程
- Thread_0线程恢复运行
- 设置_counter=0