zoukankan      html  css  js  c++  java
  • park和unpark

    1 介绍

    LockSupport类是Java6(JSR166-JUC)引入的一个类,提供了基本的线程同步原语。LockSupport提供的两个主要方法就是park和unpark。

    park译为“停车”,官方文档意为:许可。为了方便理解,在这里我们可以理解为阻塞,等待,挂起,而unpark我们理解为唤醒,恢复。

    LockSupport同步线程和wait/notify不一样,LockSupport并不需要获取对象的监视器,而是给线程一个“许可”(permit)。而permit只能是0个或者1个。unpark会给线程一个permit,而且最多是1;而park会消耗一个permit并返回,如果线程没有permit则会阻塞。

    2 特点以及与wait/notify区别

    park和unpark有以下特点

    • permit不能叠加,也就是说permit的个数要么是0,要么是1。也就是不管连续调用多少次unpark,permit也是1个。线程调用一次park就会消耗掉permit,再一次调用park又会阻塞住。举例如下
    public class App {
        public static void main(String[] args) throws Exception {
    
            Thread boyThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("boy: 我要吃鸡");
                    LockSupport.park(); 
                    System.out.println("boy: park1");
                    LockSupport.park(); // 第二次会阻塞住,因为只有一个permit
                    System.out.println("boy: park2");
                    System.out.println("boy: 开始吃鸡了");
                }
            });
    
            Thread girlThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(4000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("girl: 允许");
                    LockSupport.unpark(boyThread); // unpark两次,但是permit不会叠加
                    LockSupport.unpark(boyThread);
                }
            });
    
            boyThread.start();
            girlThread.start();
        }
    

    运行结果是

    boy: 我要吃鸡
    girl: 允许
    boy: park1
    
    • unpark可以先于park调用。也就是我们在使用park和unpark的时候可以不用担心park的时序问题造成死锁。相比之下,wait/notify存在时序问题,wait必须在notify调用之前调用,否则虽然另一个线程调用了notify,但是由于在wait之前调用了,wait感知不到,就造成wait永远在阻塞。我们可以考虑下之前的一个例子 为什么WAIT必须在同步块中, 该例子中没有使用同步块产生死锁的原因是由于错误的条件判断,导致wait调用在notify之后,所以引起线程一直挂起。而unpark和park语义更加明确,它可以指明就是让某一个线程阻塞/接触阻塞。

    • park和unpark调用的时候不需要获取同步锁。我想原因应该也是和上述类似,我们可以先分析下wait/notify需要同步锁的原因是因为两个线程存在竞态关系,必须保证在正确的条件下调用wait/notify,如果判断错误了由于调用时序问题就会造成阻塞。而park/unpark不存在时序问题,所以线程可以继续运行。

    • park的一般用法。park方法也有可能在没有"任何理由"的情况下返回,所以通常要在一个循环中使用它并重新判断可以返回的条件。这一点和Object.wait方法一样,使用模式如下:

    while (!canProceed()) { ... LockSupport.park(this); }}

    当然如果没有任何条件就park的话,也不需要while了

    3 参考

    1. http://www.ituring.com.cn/article/497544
    2. https://blog.csdn.net/xiaoliuliu2050/article/details/73998455
    3. https://blog.csdn.net/hengyunabc/article/details/28126139
    4. https://juejin.im/entry/5a13ca8251882531e9446eaa
  • 相关阅读:
    websocket 工作原理
    Flask中的wtforms使用
    DBUtils
    Django模板语言与视图(view)
    Django之图书管理系统
    Django的安装创建与连接数据库
    pymyspl模块
    多表查询与索引
    表的关系与查询
    mysql的数据类型与表约束
  • 原文地址:https://www.cnblogs.com/set-cookie/p/9582547.html
Copyright © 2011-2022 走看看