介绍:park unpark 与wait、notify很像,但是park unpark是属于每个线程私有的,而wait、notify是属于Object对象的,相同的就是两者调用后都会进入WAIT状态,没去唤醒的话就一直等待下去。park 对象由三部分组成_counter,_cond,-mutex
。
看一个例子来说明:
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
log.debug("start...");
sleep(1);
log.debug("park...");
LockSupport.park();
log.debug("resume...");
}, "t1");
t1.start();
sleep(2);
log.debug("unpark...");
LockSupport.unpark(t1);
}
输出:
当t1线程执行到LockSupport.park();
此时当前线程会去调用.park() ,检查park对象的_counter是否为0,如果等于0,将获取_mutex互斥锁,则该线程进入_cound堵塞,此时的_counter仍然为0
当main线程执行到LockSupport.unpark(t1);
counter会被设置为1,然后唤醒_cond堵塞的线程,使其继续执行,如果被unpark多次,counter值只会被设置一次。
反过来看另外一个例子:
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
log.debug("start...");
sleep(2);
log.debug("park...");
LockSupport.park();
log.debug("resume...");
}, "t1");
t1.start();
sleep(1);
log.debug("unpark...");
LockSupport.unpark(t1);
}
输出:
结果是不是挺意外的,的确如此,这就是unpark、park与wait、notyfy很大区别的一种。
主线程先醒过来然后去unpark,然后再去park,发现已经park不上去了。我们之前的如果没有wait就去notify会报java.lang.IllegalMonitorStateException
上面的例子主线程执行到LockSupport.unpark(t1);
t1的park对象_counter值被设置为1
t1线程会检查状态是否为1,如果为1这时候线程无需堵塞,继续运行,最后还会把counter设置为0。