栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JUC-LockSupport

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JUC-LockSupport

正常情况:

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " come in");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " 被唤醒");
        }, "t1");
        t1.start();
        new Thread(()->{
            LockSupport.unpark(t1);
            System.out.println(Thread.currentThread().getName() + " 发出唤醒通知");
        }, "t2").start();
    }

t1 come in
t2 发出唤醒通知
t1 被唤醒 

正常情况:先发许可证

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            System.out.println(Thread.currentThread().getName() + " come in");
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " 被唤醒");
        }, "t1");
        t1.start();
        new Thread(()->{
            LockSupport.unpark(t1);
            System.out.println(Thread.currentThread().getName() + " 发出唤醒通知");
        }, "t2").start();
    }

t2 发出唤醒通知
t1 come in
t1 被唤醒

异常情况:一个通行证,两次唤醒

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " come in");
            LockSupport.park();
            LockSupport.park();
            System.out.println(Thread.currentThread().getName() + " 被唤醒");
        }, "t1");
        t1.start();
        new Thread(()->{
            LockSupport.unpark(t1);
            LockSupport.unpark(t1);
            System.out.println(Thread.currentThread().getName() + " 发出唤醒通知");
        }, "t2").start();
    }

 


1. LockSupport原理 

 LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。

LockSupport的核心方法有两个,park和unpark,park用来阻塞当前调用线程,unpark用来唤醒指定线程。

LockSupport类使用了一种名为Permit(许可)的概念来做到阻塞和唤醒线程的功能,可以把许可看成是一种(0,1)信号量(Semaphore),但与 Semaphore 不同的是,许可的累加上限是1。

初始时,permit为0,当调用unpark()方法时,线程的permit加1,当调用park()方法时,如果permit为0,则调用线程进入阻塞状态。

2. 和Object类中的wait,notify区别

(1)wait、notify都是Object中的方法,在调用这两个方法前必须先获得锁对象,但是park不需要获得某个对象的锁就可以锁住线程。
(2)notify只能随机选择一个线程唤醒,无法对指定线程进行操作,unpark可以对指定线程唤醒。

3. LockSupport阻塞和唤醒线程原理

LockSupport就是通过控制变量_counter来对线程阻塞唤醒进行控制的。原理有点类似于semaphore信号量机制。

形象的理解,线程阻塞需要消耗凭证(permit),这个凭证最多只有1个。当调用park方法时,如果有凭证,则会直接消耗掉这个凭证然后正常退出;但是如果没有凭证,就必须阻塞等待凭证可用;而unpark则相反,它会增加一个凭证,但凭证最多只能有1个。

为什么可以先唤醒线程后阻塞线程?
因为unpark获得了一个凭证,之后再调用park因为有凭证消费,故不会阻塞。

为什么唤醒两次后阻塞两次会阻塞线程?
因为凭证的数量最多为1,连续调用2次unpark和1次unpark效果一样,只会增加一个凭证;但调用2次park则需要消耗2次凭证。

4. 总结

LockSupport是JDK用来实现线程阻塞和唤醒的工具,使用它可以在任何场合使线程阻塞,可以指定任何线程进行唤醒,不用担心阻塞和唤醒操作的顺序,不过要注意连续多次唤醒和一次唤醒的效果是一样的。
JDK并发包下的锁和其他同步工具的底层实现中大量使用了LockSupport进行线程的阻塞和唤醒。

进微信群和大佬面对面学习交流

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/281332.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号