Condition

作者: CoderZzbJohn | 来源:发表于2019-01-04 16:58 被阅读0次
    
    package com.meituan.hyt.test4;
     
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
     
     
    public class Main {
        public static void main(String[] args) {
            final ReentrantLock reentrantLock = new ReentrantLock();
            final Condition condition = reentrantLock.newCondition();
     
            new Thread(new Runnable() {
                @Override
                public void run() {
                    reentrantLock.lock();
                    System.out.println(Thread.currentThread().getName() + "拿到锁了");
                    System.out.println(Thread.currentThread().getName() + "等待信号");
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
     
                    System.out.println(Thread.currentThread().getName() + "拿到信号");
     
                    reentrantLock.unlock();
                }
            }, "线程1").start();
     
            new Thread(new Runnable() {
                @Override
                public void run() {
                    reentrantLock.lock();
                    System.out.println(Thread.currentThread().getName() + "拿到锁了");
     
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
     
                    System.out.println(Thread.currentThread().getName() + "发出信号");
                    condition.signalAll();
     
                    reentrantLock.unlock();
                }
            }, "线程2").start();
        }
    }
    

    运行结果:
    线程1拿到锁了
    线程1等待信号
    线程2拿到锁了
    线程2发出信号
    线程1拿到信号

    跟sychronized类似。
    reentrantLock.lock() 相当于sychronized(objectA)。
    condition.await() 类似于objectA.wait()
    condition.signal() 类似于 objectA.notify()

    reentrantLock.new多个condition相当于分组管理了。conditionA.await()只能由conditionA.signal()唤醒。conditionB无法唤醒。

    原理
    我们知道Lock的本质是AQS,AQS自己维护的队列是当前等待资源的队列,AQS会在资源被释放后,依次唤醒队列中从前到后的所有节点,使他们对应的线程恢复执行,直到队列为空。而Condition自己也维护了一个队列,该队列的作用是维护一个等待signal信号的队列。但是,两个队列的作用不同的,事实上,每个线程也仅仅会同时存在以上两个队列中的一个,流程是这样的:

    1. 线程1调用reentrantLock.lock时,尝试获取锁。如果成功,则返回,从AQS的队列中移除线程;否则阻塞,保持在AQS的等待队列中。
    2. 线程1调用await方法被调用时,对应操作是被加入到Condition的等待队列中,等待signal信号;同时释放锁。
    3. 锁被释放后,会唤醒AQS队列中的头结点,所以线程2会获取到锁。
    4. 线程2调用signal方法,这个时候Condition的等待队列中只有线程1一个节点,于是它被取出来,并被加入到AQS的等待队列中。注意,这个时候,线程1 并没有被唤醒,只是被加入AQS等待队列。
    5. signal方法执行完毕,线程2调用unLock()方法,释放锁。这个时候因为AQS中只有线程1,于是,线程1被唤醒,线程1恢复执行。
      所以:
      发送signal信号只是将Condition队列中的线程加到AQS的等待队列中。只有到发送signal信号的线程调用reentrantLock.unlock()释放锁后,这些线程才会被唤醒。

    可以看到,整个协作过程是靠结点在AQS的等待队列和Condition的等待队列中来回移动实现的,Condition作为一个条件类,很好的自己维护了一个等待信号的队列,并在适时的时候将结点加入到AQS的等待队列中来实现的唤醒操作。

    https://blog.csdn.net/heyutao007/article/details/49889849

    相关文章

      网友评论

          本文标题:Condition

          本文链接:https://www.haomeiwen.com/subject/wsjkrqtx.html