ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LockSupport类

2020-01-08 22:51:31  阅读:283  来源: 互联网

标签:thread Thread park LockSupport println public


LockSupport类是个工具类,主要作用是挂起和唤醒线程,是创建锁与其他同步类的基础

LockSupport类与每个使用它的线程都会关联一个许可证,默认情况下调用LockSupport类的方法的线程是不持有许可证的。LockSupport是unsafe类park、unpark方法的封装使用。

一、构造方法与变量

    private LockSupport() {} // Cannot be instantiated.工具类不能实例化

    // 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 = sun.misc.Unsafe.getUnsafe();
            Class<?> tk = Thread.class;
            parkBlockerOffset = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));
            SEED = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSeed"));
            PROBE = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomProbe"));
            SECONDARY = UNSAFE.objectFieldOffset
                (tk.getDeclaredField("threadLocalRandomSecondarySeed"));
        } catch (Exception ex) { throw new Error(ex); }
    }

二、方法

LockSupport的方法基本上是unsafe的简单封装,如下park(Object blocker)的源码。

blocker是阻塞时记录到线程内部的对象,在线程阻塞时,诊断工具可以获取对象进行分析,JDK推荐使用带参数blocker的park方法,将blocker设置为this,可打印线程堆栈排查问题时得知哪个类被阻塞了

    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);//
        UNSAFE.park(false, 0L);
        setBlocker(t, null);//
    }

三、例子及部分方法的说明

public class LockSupportTest {

    /**
     * LockSupport.park():阻塞线程
     * 当前线程已拿到LockSupport关联的许可证时,立刻返回
     * 否则阻塞挂起
     */
    @Test
    public void parkTest(){
        System.out.println("begin park!");
        LockSupport.park();
        System.out.println("end park");
    }

    /**
     * LockSupport.unpark():线程唤醒
     * 参数线程如果没有持有thread与LockSupport的关联许可证,则让线程持有,
     * park()后unpark(thread)可以唤醒park()阻塞的thread--下面unparkTest2()
     * 若unpark后park(),--下面unparkTest()
     */
    @Test
    public void unparkTest(){
        System.out.println("begin park!");
        LockSupport.unpark(Thread.currentThread());
        LockSupport.park();
        System.out.println("end park");
    }

    @Test
    public void unparkTest2() 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.start();
        Thread.sleep(1000);
        System.out.println("main thread begin unpark");
        LockSupport.unpark(thread);
    }

    /**
     * thread.interrupt()也可以引起park()的返回
     * 所以park()阻塞后返回,不会告诉是何种原因返回,所以需要根据park()原因,检查条件是否满足
     * 即是否符合条件后unpark还是被中断
     * @throws InterruptedException
     */
    @Test
    public void unparkTest3() 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.start();
        Thread.sleep(1000);
        System.out.println("main thread begin unpark");
        thread.interrupt();
    }

    public void testPark(){
        LockSupport.park(this);
    }

    /**
     * park(Object blocker),阻塞时,传入this,可检查哪个类阻塞
     * 当线程唤醒后,会清除blocker,所以一般都是在线程阻塞时才分析原因blocker
     */
    @Test
    public void parkTest1(){
        LockSupportTest test = new LockSupportTest();
        test.testPark();
    }

    /**
     * parkNanos(long nanos),阻塞nanos纳秒
     */
    @Test
    public void parkNanosTest(){
        System.out.println("begin park!");
        LockSupport.parkNanos(2000000000);//ns
        System.out.println("end park");
    }

    /**
     * parkUntil(long nanos),阻塞至deadline毫秒
     */
    @Test
    public void parkUntilTest(){
        System.out.println("begin park!");
        LockSupport.parkUntil(this, new Date().getTime() + 10000);//ms
        System.out.println("end park");
    }

}

FIFO锁

public class FIFOMutex {

    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedDeque<>();

    public void lock(){
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);

        while (waiters.peek() != current || !locked.compareAndSet(false,true)){//不是队首元素或者锁已被其他线程获取
            LockSupport.park(this);
            if (Thread.interrupted()){//如果是中断引起的返回,擦除中断标记,重新循环
                wasInterrupted = true;
            }
        }
        waiters.remove();
        if (wasInterrupted){//恢复中断标记
            current.interrupt();
        }
    }

    public void unlock(){
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }
}

标签:thread,Thread,park,LockSupport,println,public
来源: https://www.cnblogs.com/wqff-biubiu/p/12169110.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有