zoukankan      html  css  js  c++  java
  • LockSupport的用法及原理

     LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,当然阻塞之后肯定得有唤醒的方法。concurrent包是基于AQS (AbstractQueuedSynchronizer)框架的,AQS框架借助于两个类:

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

    接下面我来看看LockSupport有哪些常用的方法。主要有两类方法:park和unpark。

    public static void park(Object blocker); // 暂停当前线程
    public static void parkNanos(Object blocker, long nanos); // 暂停当前线程,不过有超时时间的限制
    public static void parkUntil(Object blocker, long deadline); // 暂停当前线程,直到某个时间
    public static void park(); // 无期限暂停当前线程
    public static void parkNanos(long nanos); // 暂停当前线程,不过有超时时间的限制
    public static void parkUntil(long deadline); // 暂停当前线程,直到某个时间
    public static void unpark(Thread thread); // 恢复当前线程
    public static Object getBlocker(Thread t);

    park函数是将当前调用Thread阻塞,而unpark函数则是将指定线程Thread唤醒。与Object类的wait/notify机制相比,park/unpark有两个优点:

    • 以thread为操作对象更符合阻塞线程的直观定义
    • 操作更精准,可以准确地唤醒某一个线程(notify随机唤醒一个线程,notifyAll唤醒所有等待的线程),增加了灵活性。

    为什么叫park呢,park英文意思为停车。我们如果把Thread看成一辆车的话,park就是让车停下,unpark就是让车启动然后跑起来。
    我们写一个例子来看看这个工具类怎么用的。

    package com.springboot.study.tests.lock;
    
    import java.util.concurrent.locks.LockSupport;
    
    /**
     * @Author: guodong
     * @Date: 2021/6/1 16:03
     * @Version: 1.0
     * @Description:
     */
    public class LockSupportDemo {
    
        public static Object u = new Object();
        static ChangeObjectThread t1 = new ChangeObjectThread("t1");
        static ChangeObjectThread t2 = new ChangeObjectThread("t2");
    
        public static class ChangeObjectThread extends Thread {
            public ChangeObjectThread(String name) {
                super(name);
            }
    
            @Override
            public void run() {
                synchronized (u) {
                    System.out.println("in " + getName());
                    LockSupport.park();
                        if (Thread.currentThread().isInterrupted()) {
                        System.out.println("被中断了");
                    }
                    System.out.println("继续执行");
                }
            }
    
        }
    
        public static void main(String[] args) throws InterruptedException {
            t1.start();
            Thread.sleep(1000L);
            t2.start();
            Thread.sleep(3000L);
            t1.interrupt();
            LockSupport.unpark(t2);
            t1.join();
            t2.join();
        }
    
    }

    运行的结果如下:

    in t1
    被中断了
    继续执行
    in t2
    继续执行

    这儿park和unpark其实实现了wait和notify的功能,不过还是有一些差别的。

    • park不需要获取某个对象的锁
    • 因为中断的时候park不会抛出InterruptedException异常,所以需要在park之后自行判断中断状态,然后做额外的处理

    总结一下

    • park和unpark可以实现类似wait和notify的功能,但是并不和wait和notify交叉,也就是说unpark不会对wait起作用,notify也不会对park起作用。
    • park和unpark的使用不会出现死锁的情况
    • blocker的作用是在dump线程的时候看到阻塞对象的信息

  • 相关阅读:
    HAproxy 1.5 dev14 发布
    IBM/DW 使用 Java 测试网络连通性的几种方法
    Skype 4.1 Linux 发布,支持微软帐号登录
    Dorado 7.1.20 发布,Ajax的Web开发平台
    Aspose.Slides for Java 3.0 发布
    开发版本 Wine 1.5.18 发布
    BitNami Rubystack 开始支持 Ruby 2.0
    XWiki 4.3 正式版发布
    Silverlight实例教程 Out of Browser的Debug和Notifications窗口
    Silverlight实例教程 Out of Browser与Office的互操作
  • 原文地址:https://www.cnblogs.com/jelly12345/p/14837628.html
Copyright © 2011-2022 走看看