其他分享
首页 > 其他分享> > 浅谈LockSupport工具类

浅谈LockSupport工具类

作者:互联网

Java的并发包是基于AQS (AbstractQueuedSynchronizer)框架的,AQS框架需要借助于两个工具类:

LockSupport的使用

LockSupport定义了一组公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能。LockSupport定义了一组以park开头的方法用来阻塞当前线程,以及unpark(Thread thread)方法来唤醒一个被阻塞的线程。

在Java6中,LockSupport增加了三个带有blocker的方法。参数blocker用来指出当前线程在等待的对象,即阻塞对象,该对象主要用于问题排查和系统监控。

public static void park(Object blocker); // 暂停当前线程
public static void parkNanos(Object blocker, long nanos); // 暂停当前线程,不过有超时时间的限制
public static void parkUntil(Object blocker, long deadline); // 暂停当前线程,直到某个时间

现在通过具体代码看看是如何使用的

LockSupport的原理(以park和unpark为例说明)

1. 源码分析

归根结底,LockSupport.park()和LockSupport.unpark(Thread thread)调用的是Unsafe类中的native代码:

//LockSupport中
public static void park() {
        UNSAFE.park(false, 0L);
    }

public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }

Unsafe类中的对应方法:

//park
public native void park(boolean isAbsolute, long time);
    
//unpack
public native void unpark(Object var1);

Unsafe.park()和Unsafe.unpark()的底层,在Linux系统下,是用的POSIX的线程库pthread中的mutex(互斥量),condition(条件变量)来实现的,即互斥锁+条件变量。mutex和condition保护了一个_counter的变量,当park时,这个变量被设置为0,当unpark时,这个变量被设置为1。

2. 特性和思想

2.1 许可

LockSupport类使用了一种名为permit(许可)的概念来做到阻塞和唤醒线程的功能,可以把许可看成是一种(0,1)信号量,但这个许可的累加上限是1。初始时,permit为0,当调用unpark()方法时,线程的permit加1,当调用park()方法时,如果permit为0,则调用线程进入阻塞状态。也就是说,park/unpark的设计原理核心是“许可”:park是等待一个许可,unpark是为某线程提供一个许可。如果某线程A调用park,那么除非另外一个线程调用unpark(A)给A一个许可,否则线程A将阻塞在park操作上。

但是这个“许可”是不能叠加的,“许可”是一次性的。比如线程B连续调用了三次unpark函数,当线程A调用park函数就使用掉这个“许可”,如果线程A再次调用park,则进入等待状态。

2.2 顺序

park和unpark的先后顺序并不是那么严格,即unpark操作可以再park操作之前。这时候规则是这样的:

  1. unpark调用时,如果当前线程还未进入park,则许可为true
  2. park调用时,判断许可是否为true,如果是true,则继续往下执行;如果是false,则等待,直到许可为true

LockSupport和wait/notify的区别

参考资料

LockSupport详解

LockSupport的用法及原理

Java多线程进阶(五)—— J.U.C之locks框架:LockSupport

 

标签:调用,浅谈,park,LockSupport,unpark,线程,工具,许可
来源: https://blog.csdn.net/qq_42052956/article/details/112389030