• LockSupport详解


    LockSupport详解

    简介

    • LockSupport用来创建锁或其他同步类的基本线程阻塞原语.
    • 调用park()方法时,当前线程将等待,直到获取许可.
    • 调用unpark()方法时,必须将等待获得许可的线程作为参数,使得等待的线程继续进行.

    核心方法

    Unsafe类的park和unpark

    LockSupport的park()unpark()是调用Unsafe类的park()unpark()实现的.

    • park():阻塞线程.
    • unpark():释放线程,激活调用park()后阻塞的线程.

    park()方法

    // 调用park后线程会被阻塞,三种情况下线程获得许可:
    // 1. 其他线程调用此线程的unpark()
    // 2. 其他线程中断此线程
    // 3. 该调用无理由返回
    public static void park(Object blocker) {
        Thread t = Thread.currentThread();
        setBlocker(t, blocker); // 设置当前线程的blocker
        UNSAFE.park(false, 0L); // 阻塞当前线程
        setBlocker(t, null); // 设置当前线程的blocker为null
    }
    

    注:(调用两次设置blocker的原因)
    首次设置好blocker后,调用park()阻塞线程,等待其他线程调用unpark()来激活线程.
    当前线程再次被激活后,再次设置blocker为null.否则,在获取blocker时,得到的是上一次设置的blocker.

    parkNanos

    在许可可用前阻塞当前线程,最多等待指定的等待时间.

    parkUntil

    在指定时限前禁止当前线程,除非许可可用.

    unpark

    • 若给定线程的许可不可用,则使其可用,解除阻塞状态.
    • 若线程未启动,则无效果.

    使用park/unpark实现线程同步

    示例:

    // 一个park阻塞的线程,被其他线程unpark()后继续执行
    threadA t1 = new threadA();
    
    t1.start();
    
    LockSupport.unpark(t1);
    
    // t1.interrupt(); // 中断park的线程也可将其唤醒
    
    // --------------------
    class threadA{
        Thread.sleep(1000); // 先unpark,再park一样可行
        LockSupport.park();
        System.out.println(Thread.currentThread().getName());
    }
    
    // 先对一个线程unpark(),然后其调用park()后,线程继续执行
    threadA t1 = new threadA();
    
    t1.start();
    
    
    
    LockSupport.unpark(t1);
    
    // t1.interrupt(); // 中断park的线程也可将其唤醒
    
    // --------------------
    class threadA{
        LockSupport.park();
        System.out.println(Thread.currentThread().getName());
    }
    

    小结

    Thread.sleep()与Object.wait()的区别

    Thread.sleep() Object.wait()
    不会释放占有的锁 会释放占有的锁
    参数 必须传入睡眠的时间 可以传时间,也可不传
    时间 时间到了会自动唤醒,继续执行 没有时间,需要等待notify唤醒;有时间,则被唤醒或时间到了自动唤醒

    Thread.sleep()与Condition.await()的区别

    基本相同,Condition.await()是调用LockSupport.part()阻塞当前线程.

    流程:

    1. 将当前线程加入条件队列.
    2. 释放锁.
    3. 调用LockSupport.park()阻塞当前线程.

    Thread.sleep()和LockSupport.park()的区别

    Thread.sleep() LockSupport.park()
    功能 阻塞当前线程,不释放占有的锁 阻塞当前线程,不释放占有的锁
    唤醒 只能自己唤醒自己 可以被其他线程通过unpark()唤醒
    异常 声明抛出异常 不需要捕获异常

    Object.wait()和LockSupport.park()的区别

    Object.wait() LockSupport.park()
    使用 只能在synchronized块执行 在任意地方执行
    异常 声明抛出中断异常 不需要捕获异常
    超时 不带超时,需要其他线程执行notify()唤醒 不带超时,需要其他线程执行unpark()唤醒
    睡眠前唤醒 抛出异常 不会被阻塞,跳过park(),继续执行

    参考:

  • 相关阅读:
    自动化运维
    rabbitmq常见问题
    常见的排序算法
    rabbitmq
    redis-其他应用
    redis之缓存穿透、雪崩、击穿
    redis-cluster(集群)
    redis -sentinel(哨兵)
    redis持久化
    redis简介
  • 原文地址:https://www.cnblogs.com/truestoriesavici01/p/13224742.html
Copyright © 2020-2023  润新知