前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >并发编程系列之掌握LockSupport的用法

并发编程系列之掌握LockSupport的用法

作者头像
SmileNicky
发布2021-11-17 10:50:02
3670
发布2021-11-17 10:50:02
举报
文章被收录于专栏:Nicky's blog

并发编程系列之掌握LockSupport的用法

1、什么是LockSupport?

LockSupport是用于创建锁和其他同步类的基本线程阻塞原语

2、两类基本API

LockSupport提供了两类最基本的API:

  • block线程类:一般都是以pack开头的方法名,pack*(...) pack方法有两个重载的版本:blocker是一个对象,用于指定阻塞哪个对象。不知道的情况,默认以锁对象自己this为blocker
代码语言:javascript
复制
public static void park();
public static void park(Object blocker);

拓展: parkNanos函数

代码语言:javascript
复制
public static void parkNanos(Object blocker, long nanos) {
    if (nanos > 0) { 
        // 获取当前线程
        Thread t = Thread.currentThread();
        // 设置Blocker
        setBlocker(t, blocker);
        // 获取许可,并设置了时间
        UNSAFE.park(false, nanos);
        // 设置许可,重新设置blocker为null,避免unpack,获取的blocker为之前设置的
        setBlocker(t, null);
    }
}

nanos参数表示相对时间,表示等待多长时间

parkUntil函数:表示在指定的时限前禁用当前线程,deadline参数表示绝对时间,表示指定的时间

代码语言:javascript
复制
public static void parkUntil(Object blocker, long deadline) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 设置Blocker
    setBlocker(t, blocker);
    UNSAFE.park(true, deadline);
    // 设置Blocker为null
    setBlocker(t, null);
}
  • unBlock线程类:unpack(Thread) unpack方法用于释放许可,指定线程可以继续运行。

3、LockSupport本质

LockSupport是一个许可的信号量机制,pack消费,unpack放入,放入也是仅一个,不累计。例如,调用unpack放入一个信号量,多次调用,这个是不会累计信号量的,pack调用之后会消费

4、LockSupport例子

例子:如何控制两个线程依次打印1、2、3、4、5、6、…

代码语言:javascript
复制
import java.util.concurrent.locks.LockSupport;
public class LockSupportExample {
    private static final int total = 10;
    private  static int i = 0;
    static Thread t1 , t2;
    public static void main(String[] args) {
        t1 = new Thread(() ->{
            while (i < total) {
                System.out.println("t1:" + (++i));
                LockSupport.unpark(t2);
                LockSupport.park();
            }
        });
        t2 = new Thread(() -> {
            while (i < total) {
                LockSupport.park();
                System.out.println("t2:" + (++i));
                LockSupport.unpark(t1);
            }
        });
        t1.start();
        t2.start();
    }
}

打印:

t1: 1 t2: 2 t1:3 t2:4 t1:5 t2:6 t1:7 t2:8 t1:9 t2:10

5、LockSupport源码

代码语言:javascript
复制
public class LockSupport {
    // Hotspot implementation via intrinsics API
    private static final sun.misc.Unsafe UNSAFE;
    
    private static final long parkBlockerOffset;
    
    private static final long SEED;
   
    private static final long PROBE;
  
    private static final long SECONDARY;
    
    static {
        try {
            // 获取Unsafe实例
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            // 线程类的class对象
            Class<?> tk = Thread.class;
            // 获取Thread的parkBlocker字段的内存偏移地址
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            // 获取Thread的threadLocalRandomSeed字段的内存偏移地址
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            // 获取Thread的threadLocalRandomProbe字段的内存偏移地址
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            // 获取Thread的threadLocalRandomSecondarySeed字段的内存偏移地址
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }
}

pack方法的源码:

代码语言:javascript
复制
public static void park(Object blocker) {
    // 获取当前线程
    Thread t = Thread.currentThread();
    // 设置Blocker
    setBlocker(t, blocker);
    // 获取许可
    UNSAFE.park(false, 0L);
    // 重新可运行后再此设置Blocker为null,避免unpack获取到上一个设置的setBlocker(t, blocker);
    setBlocker(t, null);
}

unpack的源码:

代码语言:javascript
复制
public static void unpark(Thread thread) {
    if (thread != null) // 线程为不空
        UNSAFE.unpark(thread); // 释放该线程许可
}

可以看出,不管是pack的源码还是unpack的源码都是通过Unsafe的底层api实现的

  • sun.misc.Unsafe详解 可以直接进行底层非安全操作的工具类,主要提供如下操作:
  • 线程挂起与恢复
  • CAS操作
  • 操纵对象属性
  • 操纵数组元素
  • 直接操纵内存

参考资料

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、什么是LockSupport?
  • 2、两类基本API
  • 3、LockSupport本质
  • 4、LockSupport例子
  • 5、LockSupport源码
  • 参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档