zoukankan      html  css  js  c++  java
  • 并发编程-condition

     Condition是一个多线程协调通信的工具类,可以让某些线程一起等待某个条件(condition),只有满足条件时,线程才会被唤醒

    condition中两个最重要的方法,一个是await,一个是signal方法

    await:把当前线程阻塞挂起

    signal:唤醒阻塞的线程

    示例:

    public class ConditionWait implements Runnable{
    
        private Lock lock;
        private Condition condition;
    
        public ConditionWait(Lock lock, Condition condition) {
            this.lock = lock;
            this.condition = condition;
        }
        @Override
        public void run() {
            try {
                lock.lock(); //竞争锁
                try {
                    System.out.println("begin - ConditionWait");
                    condition.await();//阻塞(1. 释放锁, 2.阻塞当前线程, FIFO(单向、双向))
                    System.out.println("end - ConditionWait");
    //                condition.signal();
    
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }finally {
                lock.unlock();//释放锁
            }
    
    
        }
    
    
    }
    public class ConditionNotify implements Runnable{
    
        private Lock lock;
        private Condition condition;
    
        public ConditionNotify(Lock lock, Condition condition) {
            this.lock = lock;
            this.condition = condition;
        }
    
        @Override
        public void run() {
            try{
                lock.lock();//获得了锁.
                System.out.println("begin - conditionNotify");
                condition.signal();//唤醒阻塞状态的线程
    
                //if(uncondition){
    //                condition.await();
                // }
                //condition.notify;
    
                condition.await();
                System.out.println("end - conditionNotify");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock(); //释放锁
            }
        }
    }
    public class App 
    {
        public static void main( String[] args )
        {
            Lock lock=new ReentrantLock(); //重入锁
            Condition condition=lock.newCondition();
    
            //step 2
            new Thread(new ConditionWait(lock,condition)).start();// 阻塞await
            //step 1
            //(condtion为空)
            new Thread(new ConditionNotify(lock,condition)).start();//
        }
    }

    线程awaitThread先通过lock.lock()方法获取锁成功后调用了condition.await方法进入等待队列,而另一个线程signalThread通过lock.lock()方法获取锁成功后调用了condition.signal或者signalAll方法,使得线程awaitThread能够有机会移入到同步队列中,当其他线程释放lock后使得线程awaitThread能够有机会获取lock,从而使得线程awaitThread能够从await方法中退出执行后续操作。如果awaitThread获取lock失败会直接进入到同步队列。

    阻塞:await()方法中,在线程释放锁资源之后,如果节点不在AQS等待队列,则阻塞当前线程,如果在等待队列,则自旋等待尝试获取锁

    释放:signal()后,节点会从condition队列移动到AQS等待队列,则进入正常锁的获取流程

     

    Condition源码分析

    调用Condition,需要获得Lock锁,所以意味着会存在一个AQS同步队列,

    condition.await

    调用Condition的await()方法(或者以await开头的方法),会使当前线程进入等待队列并释放锁,同时线程状态变为等待状态。当从await()方法返回时,当前线程一定获取了Condition相关联的锁

    addConditionWaiter

    这个方法的主要作用是把当前线程封装成Node,添加到等待队列。这里的队列不再是双向链表,而是单向链表

    fullyRelease

    fullRelease,就是彻底的释放锁,什么叫彻底呢,就是如果当前锁存在多次重入,那么在这个方法中只需要释放一次就会把所有的重入次数归零。

    isOnSyncQueue

    判断当前节点是否在同步队列中,返回false表示不在,返回true表示在

    如果不在AQS同步队列,说明当前节点没有唤醒去争抢同步锁,所以需要把当前线程阻塞起来,直到其他的线程调用signal唤醒

    如果在AQS同步队列,意味着它需要去竞争同步锁去获得执行程序执行权限

    为什么要做这个判断呢?原因是在condition队列中的节点会重新加入到AQS队列去竞争锁。也就是当调用signal的时候,会把当前节点从condition队列转移到AQS队列

    ➢ 大家思考一下,基于现在的逻辑结构。如何去判断ThreadA这个节点是否存在于AQS队列中呢?

    1. 如果ThreadA的waitStatus的状态为CONDITION,说明它存在于condition队列中,不在AQS队列。因为AQS队列的状态一定不可能有CONDITION

    2. 如果node.prev为空,说明也不存在于AQS队列,原因是prev=null在AQS队列中只有一种可能性,就是它是head节点,head节点意味着它是获得锁的节点。

    3. 如果node.next不等于空,说明一定存在于AQS队列中,因为只有AQS队列才会存在next和prev的关系

    4. findNodeFromTail,表示从tail节点往前扫描AQS队列,一旦发现AQS队列的节点和当前节点相等,说明节点一定存在于AQS队列中

     

  • 相关阅读:
    第一个WCF的程序
    第一节 SOA的基本概念和设计思想
    数组拷贝 copyOf()
    dict和set
    类的构造函数
    深入理解 Python 异步编程(上)
    Nifi自定义processor
    java inputstream to string stack overflow
    java inputstream to string
    oracle 导入 dmp
  • 原文地址:https://www.cnblogs.com/yintingting/p/6582619.html
Copyright © 2011-2022 走看看