Condition源码简析

即使你不了解并发编程,你也肯定听过wait和notify,如果你非要说没听过,那么就…那么就…
wait和notify是配合synchronized关键字使用的,如果我们想使用ReentrantLock,那么如何来实现等待和唤醒的功能呢?

答案就是使用Condition,先来一段小demo吧

public class Demo {
    static ReentrantLock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();

    public static void main(String[] args) throws Exception {
        new Thread(){
            @Override
            public void run() {
                System.out.println("第一个线程加锁");
                lock.lock();
                try {
                    System.out.println("第一个线程释放锁&阻塞");
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("第一个线程释放锁");
                lock.unlock();
            }
        }.start();

        Thread.sleep(3000);

        new Thread(){
            @Override
            public void run() {
                System.out.println("第二个线程加锁");
                lock.lock();
                System.out.println("二个线程唤醒第一个线程");
                condition.signal();
                System.out.println("第二个线程释放锁");
                lock.unlock();
            }
        }.start();
    }
}

如果你运行这个demo的话,结果是

第一个线程加锁
第一个线程释放锁&阻塞
第二个线程加锁
二个线程唤醒第一个线程
第二个线程释放锁
第一个线程释放锁

那么Condition在底层是如何来实现等待和唤醒的功能的呢?
讲Condition的话依旧是绕不开AQS,如果不了解AQS的话,可以先看我的这篇ReentrantReadWriteLock简析,或者直接看这篇微信公众号的文章

如果你已经了解了AQS的话,我们接着往下看,就拿上面的demo来讲一下流程
首先线程1获取到了锁,之后调用了condition.await()方法,在这个方法中,要做的第一件事,就是跟AQS中的加锁等待队列一样,创建了一个Condition的等待队列,然后将线程1加入到了Condition等待队列中,之后线程1会释放锁并将自己挂起
await
线程2在线程1释放锁之后获取到了锁,之后调用了condition.signal()方法,这个方法中其实就是将Condition等待队列中的线程1放到了AQS中的加锁等待队列中
signal
通过上面两张图,我们知道了condition的await和signal方法都做了些什么,下面再来梳理一下整个流程

  1. 线程1获取锁
  2. 线程1调用condition.await()方法,将自己放入Condition等待队列,同时释放锁并挂起自己
  3. 线程2获取锁
  4. 线程2将线程1由Condition等待队列转移到加锁等待队列中
  5. 线程2释放锁
  6. 线程2释放了之后,唤醒了在加锁等待队列中的线程1,然后线程1继续执行完自己的逻辑之后释放锁

整个流程走完,就分别对应了demo的每一步的输出内容

其实Condition的原理就是这么简单,里面就是使用了一个Condition的等待队列来存储调用了await方法的线程,当signal唤醒等待中的线程时,就将线程加入到加锁队列中,继续去争抢锁,得到了锁之后再执行被挂起之后的逻辑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值