zoukankan      html  css  js  c++  java
  • 并发编程(五)LockSupport

    并发编程(五)LockSupport

    LockSupport 提供 park() 和 unpark() 方法实现阻塞线程和解除线程阻塞,实现的阻塞和解除阻塞是基于“许可(permit)”作为关联,permit 相当于一个信号量(0,1),默认是0。 线程之间不再需要一个 Object 或者其它变量来存储状态,不再需要关心对方的状态。

    一、LockSupport API

    (1) pack

    方法 说明
    park() 挂起当前线程
    park(Object blocker) 挂起当前线程
    parkNanos(long nanos) 指定挂起时间(相对于当前的时间),时间到后自动被唤醒
    parkNanos(Object blocker, long nanos) 指定挂起时间(相对于当前的时间)
    parkUntil(long deadline) 指定挂起时间(绝对时间),时间到后自动被唤醒
    parkUntil(Object blocker, long deadline) 指定挂起时间(绝对时间),时间到后自动被唤醒

    从上面表格可以看出,park 支持 blocker 对象作为参数,该字段是 Thread 类,专门为 LockSupport 而设计的。此 blocker 对象在线程受阻塞时被记录,这样监视工具和诊断工具就可以确定线程受阻塞的原因。建议最好使用这些带 blocker 的方法版本,而不是不带 blocker 参数的方法。

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

    (2) unpark

    设置线程许可为可用。

    • 如果线程当前已经被 pack 挂起,那么这个线程将会被唤醒。
    • 如果线程当前没有被挂起,那么下次调用 pack 不会挂起线程。
    public static void unpark(Thread thread) {
        if (thread != null)
            UNSAFE.unpark(thread);
    }
    

    二、LockSupport 使用

    (1) 先park后unpark

    public void test1() throws Exception {
        Thread mainThread = Thread.currentThread();
        Thread thread = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            System.out.println("before unpark, " + LockSupport.getBlocker(mainThread));
            LockSupport.unpark(mainThread);
            System.out.println("after unpark, " + LockSupport.getBlocker(mainThread));
        });
        thread.start();
        System.out.println("before park");
        // 等待获取许可
        LockSupport.park("Park");
        System.out.println("after park");
    }
    

    结果:

    before park
    before unpark, Park
    after park
    after unpark, null
    

    (2) 先unpark后unpark

    先执行 unpark,在调用 park,直接就没被阻塞, 因此 park/unpark 相比 wait/notify 更加的灵活

    public void test2() throws Exception {
        Thread mainThread = Thread.currentThread();
        Thread thread = new Thread(() -> {
            System.out.println("before unpark, " + LockSupport.getBlocker(mainThread));
            LockSupport.unpark(mainThread);
            System.out.println("after unpark, " + LockSupport.getBlocker(mainThread));
        });
        thread.start();
    
        TimeUnit.SECONDS.sleep(1);
        System.out.println("before park");
        // 等待获取许可
        LockSupport.park("Park");
        System.out.println("after park");
    }
    

    (2) park与interrupt

    public void test3() throws Exception {
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().isInterrupted()); // false
            LockSupport.park();
            System.out.println(Thread.currentThread().isInterrupted()); // true
        });
        thread.start();
    
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
        System.in.read();
    }
    

    简而言之:

    1. 实现机制和 wait/notify 有所不同,面向的是线程
    2. 不需要依赖监视器
    3. 与 wait/notify 没有交集
    4. 使用起来方便灵活

    参考:

    1. 《LockSupport解析与使用》:https://blog.csdn.net/secsf/article/details/78560013

    每天用心记录一点点。内容也许不重要,但习惯很重要!

  • 相关阅读:
    HDU 1060 Leftmost Digit
    HDU 1008 Elevator
    HDU 1042 N!
    HDU 1040 As Easy As A+B
    HDU 1007 Quoit Design
    欧拉函数
    HDU 4983 Goffi and GCD
    HDU 2588 GCD
    HDU 3501 Calculation 2
    HDU 4981 Goffi and Median
  • 原文地址:https://www.cnblogs.com/binarylei/p/10074774.html
Copyright © 2011-2022 走看看