美文网首页工作生活
J.U.C之LockSupport:线程等待和唤醒

J.U.C之LockSupport:线程等待和唤醒

作者: 贪睡的企鹅 | 来源:发表于2019-07-03 13:21 被阅读0次

    1 LockSupport 概述

    LockSupprot是线程的阻塞原语,用来阻塞线程和唤醒线程。每个使用LockSupport的线程都会与一个许可关联,如果该许可可用,并且可在线程中使用,则调用park()将会立即返回,否则可能阻塞。如果许可尚不可用,则可以调用 unpark 使其可用。但是注意许可不可重入,也就是说只能调用一次park()方法,否则会一直阻塞。

    2 LockSupport API

    获取许可相关

    //获取许可,如果成功则直接返回,失败则一直阻塞当前线程。
    //直到系统调用unpark方法或者当前线程被中断时可以从阻塞中唤醒从park()方法中返回
    public static void park() {
            UNSAFE.park(false, 0L);
    }
    
    //功能同park()方法,增加了一个Object对象参数,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(false, 0L);
        setBlocker(t, null);
    }
    
    //功能同park()方法,增加了一个超时时间nanos(纳秒),如果线程获取许可失败,阻塞不再是永久,而时增加了超时返回的特性;
    public static void parkNanos(long nanos) {
            if (nanos > 0)
                UNSAFE.park(false, nanos);
    }
    
    //功能同parkNanos,增加了一个Object对象参数,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;
    public static void parkNanos(long nanos) {
        if (nanos > 0)
            UNSAFE.park(false, nanos);
    }
    
    //功能同park()方法,这里超时时间变成了绝对的超时时间,超时时间单位变成纳秒。
    public static void parkUntil(long deadline) {
        UNSAFE.park(true, deadline);
    }
    
    //功能同parkUntil,增加了一个Object对象参数,用来记录导致线程阻塞的阻塞对象,方便进行问题排查;    
    public static void parkUntil(Object blocker, long deadline) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker);
        UNSAFE.park(true, deadline);
        setBlocker(t, null);
    }    
    

    释放许可

         //释放一个线程的许可。如果线程在等待许可阻塞,会被唤醒。
         public static void unpark(Thread thread) {
            if (thread != null)
                UNSAFE.unpark(thread);
        }
    

    线程dump

    UNSAFE

    LockSupport 实现上通过UNSAFE实现。特性上和UNSAFE相同,我们来回顾下UNSAFE 特性:

    • 默认情况下线程中不存在许可。当前线程第一次使用Unsafe 调用park方法时(如果未调用unpark)会导致当前线程阻塞。

    • 同一个线程多次归还许可只和一次归还相同

    • unpark 无法恢复处于 sleep 中的线程,只能与 park 配对使用,因为 unpark 发放的许可只有 park 能监听到。

    使用例子

    package locksupport;
    
    import org.junit.Test;
    
    import java.util.concurrent.locks.LockSupport;
    
    public class LockSupportTest {
    
        @Test
        public void park1(){
            LockSupport.park();
        }
    
        @Test
        public void park2(){
            long star=System.currentTimeMillis();
            LockSupport.parkNanos(5000000000L);
            System.out.println(System.currentTimeMillis()-star);
        }
    
    
        @Test
        public void park3(){
            long star=System.currentTimeMillis();
            LockSupport.parkUntil(System.currentTimeMillis()+5000L);
            System.out.println(System.currentTimeMillis()-star);
        }
    
    
    
        @Test
        public void park5() {
            Thread currThread = Thread.currentThread();
            LockSupport.unpark(currThread);
            LockSupport.unpark(currThread);
            LockSupport.unpark(currThread);
            LockSupport.park();
            LockSupport.park();
            System.out.println("execute success"); // 线程挂起,不会打印。
        }
    }
    
    

    相关文章

      网友评论

        本文标题:J.U.C之LockSupport:线程等待和唤醒

        本文链接:https://www.haomeiwen.com/subject/cveqhctx.html