浅谈LockSupport工具类

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

  • Unsafe(提供CAS操作)
  • LockSupport(提供park/unpark操作)

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以线程为操作对象更符合阻塞线程的直观定义。
  • 操作更精准,可以准确地唤醒某一个线程,增加了灵活性。而notify随机唤醒一个线程,notifyAll唤醒所有等待的线程。
  • wait和notify都是Object中的方法,在调用这两个方法前必须先获得对象的锁,但是park不需要获取某个对象的锁就可以锁住线程。

参考资料

LockSupport详解

LockSupport的用法及原理

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值