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&notify&notifyAll

  • wait, notify, notifyAll必须配合Object Monitor一起使用,而park, unpark不用。
  • park, unpark是以线程为单位来【阻塞】和【唤醒】线程,而notify只能随机唤醒一个线程,notifyAll是唤醒所有等待的线程,而不是很【精确】
  • (从上面的代码看到)可以先unpark再park,而wait和notify则需要按顺序

原理

每个线程都有自己一个Parker对象,由_couter, _cond, _mutex三部分组成。

  • LockSupport.park()
  1. 当前线程调用park()方法
  2. 检查_counter,若为0,此时,获得_mutex互斥锁;若为1,线程无需阻塞,继续运行(这是先unpark再park的情况)。
  3. 线程进入_cond条件变量阻塞
  4. 设置_counter=0
  • LockSupport.unpark()
  1. 调用unpark(t)方法,设置_counter为1
  2. 唤醒_cond条件变量中的Thread_0线程
  3. Thread_0线程恢复运行
  4. 设置_counter=0