Java并发编程之LockSupport类

这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战

JDK中的rt.jar包中的LockSupport是个工具类,它的主要作用是挂起和唤醒线程,该工具类是创建锁和其他同步类的基础。

LockSupport类与每个使用它的线程都会关联一个许可证,在默认情况下调用LockSupport类的方法的线程是不持有许可证的。LockSupport是使用Unsafe类实现,下面介绍LockSupport中的几个函数。

1.void park()方法

如果调用park方法的线程已经拿到了与LockSupport关联的许可证,则调用LockSupport关联的许可证,则调用LockSupport.park()时,会立即返回,否则调用线程会被禁止参与线程的调度,也就是被阻塞挂起。

public static void main(String[] args) {
    System.out.println("begin park");
    LockSupport.park();
    System.out.println("end park");
}
复制代码

在其他线程调用unpark()方法并且将当前线程作为参数时,调用park方法而被阻塞的线程会返回。另外如果其他线程调用了阻塞线程的interrupt()方法,设置了中断标志或者线程被虚假唤醒,则阻塞线程也会返回。所以在调用park方法时,最好使用循环条件判断方式。因调用park()方法而被阻塞的线程被其他线程中断而返回时并不会抛出InterruptedException异常。

  1. void unpark(Thread thread)方法

当一个线程调用unpark时,如果参数thread线程没有持有thread与LockSupport类关联的许可证,则让thread线程持有。如果thread之前因调用park()而被挂起,则调用unpark后,则该线程会被唤醒。如果thread之前没有调用park,则调用unpark方法后,再调用park方法,其会立即返回。

public static void main(String[] args) throws InterruptedException{
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("child thread begin park!");
            LockSupport.park();
            System.out.println("child thread unpark!");
        }
    });
    
    Thread.sleep(1000);
    System.out.println("main thread begin unpark!");
    LockSupport.unpark(thread);
}
复制代码

park方法返回时不会告诉你因何种原因返回,所以调用者需要根据之前调用park方法的原因,再次检查条件是否满足,如果不满足还需要再次调用park方法。 例如,根据调用park方法后的线程被中断后返回,我们修改上面的例子代码,删除LockSupport.Unpark(thread);然后添加thread.interrupt()。

public static void main(String[] args) throws InterruptedException{
    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("child thread begin park!");
            while (!Thread.currentThread().isInterrupted()) {
                LockSupport.park();
            }
            System.out.println("child thread unpark!");
        }
    });

    Thread.sleep(1000);
    System.out.println("main thread begin unpark!");
    thread.interrupt();
}
复制代码

在如上代码中,只用中断子线程,子线程才会运行结束,如果子线程不被中断,即使调用unpark方法,子线程也不用结束。

  1. void parkNanos(long nanos)方法

与park方法类似,只不过是当调用park被挂起namos时间后,会自动返回。

  1. park (Object blocker)
public static void park(Object blocker) {
    Thread t = Thread.currentThread();
    setBlocker(t, blocker);
    UNSAFE.park(false, 0L);
    setBlocker(t, null);
}
复制代码

park方法还支持带有blocker参数的方法,当线程在没有持有许可证的情况下调用park方法而被阻塞挂起时候,这个blocker对象会被记录到该线程内部。

Guess you like

Origin juejin.im/post/7034760639042027528