LockSuport-park()/unpark()
每个线程在底层都会关联一个parker对象; parker对象中有三个属性
-
_mutex 互斥量
-
_cond 条件量
-
_couter 阻塞标记
当调用park方法, counter设置为0, 线程进入阻塞
调用unpark, counter设置为1, 线程唤醒
方法特性:
-
park()`方法:调用park()方法会使当前线程进入阻塞状态,暂停执行,直到满足某种条件才会解除阻塞。park()方法提供了灵活的阻塞控制,可以在任意位置调用。如果调用park()方法时已经满足解除阻塞的条件,则park()方法立即返回,否则线程将被阻塞。一下是park不发生阻塞的情况:
- 被调用的
unpark()
方法被调用:在调用park()
方法之前,如果已经有对应线程的unpark()
方法被调用过,那么park()
方法会立即返回,不会阻塞。 - 其他线程调用当前线程的
interrupt()
方法:如果在调用park()
方法之前,其他线程中断了当前线程,并且当前线程没有被unpark()
方法解除阻塞,那么park()
方法也会立即返回,不会阻塞,并且会清除中断状态。 - 虚假唤醒:虽然不符合预期的条件,但线程也可能在没有被显式唤醒**(调用notify方法)**的情况下从
park()
方法中返回。这种情况被称为虚假唤醒(spurious wake-up)。为了防止虚假唤醒的问题,一般建议在park()
方法返回后再次检查等待条件。
- 被调用的
-
unpark()
方法:unpark()方法用于解除通过park()方法造成的阻塞状态,使得被阻塞的线程可以继续执行。unpark()方法可以指定解除阻塞的线程,即使该线程尚未进入阻塞状态,下一次调用park()方法时也会立即返回。 -
unpark()
方法的先行发生性:unpark()方法具有先行发生性,即在调用park()方法之前调用unpark()方法,被阻塞的线程调用park()方法时可以立即返回,而不会阻塞。 -
unpark()
方法的不累积性:unpark()方法不会累积许可,即多次调用unpark()方法只会提供一个许可。无论调用unpark()方法的次数是一次还是多次,被阻塞的线程只需消费一次许可即可解除阻塞。