并发编程第9篇,Condition

Condition

private static Lock lock = new ReentrantLock();

  private static Condition condition = lock.newCondition();

  public static void main(String[] args) throws InterruptedException {

    Thread thread = new Thread(() -> {

        lock.lock();

        try {

            System.out.println(Thread.currentThread().getName() + ":1");

            condition.await();

            System.out.println(Thread.currentThread().getName() + ":2");

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    });

    thread.start();

    try {

        Thread.sleep(3000);

    } catch (Exception e) {

  

    }

    lock.lock();

    // 唤醒

    condition.signal();

    lock.unlock();

    System.out.println(Thread.currentThread().getName() + ":3");

  

}

 

Condition源码分析

Condition是一个接口,其提供的就两个核心方法,await和signal方法。分别对应着Object的wait和notify方法。调用Object对象的这两个方法,需要在同步代码块里面,即必须先获取到锁才能执行这两个方法。同理,Condition调用这两个方法,也必须先获取到锁


1.等待队列:用于存放在lock锁中调用await方法,当前线程会变为阻塞状态,

同时会释放锁 单向链表存放

  1. 同步队列:用于存放没有竞争到锁,采用双向链表存放。

 

等待池

 

Condition简单用法

private static Lock lock = new ReentrantLock();

  private static Condition condition = lock.newCondition();

  

  public static void main(String[] args) throws InterruptedException {

    Thread thread = new Thread(() -> {

        lock.lock();

        try {

            System.out.println(Thread.currentThread().getName() + ":1");

            condition.await();

            System.out.println(Thread.currentThread().getName() + ":2");

        } catch (InterruptedException e) {

            e.printStackTrace();

        }

    });

    thread.start();

    try {

        Thread.sleep(3000);

    } catch (Exception e) {

  

    }

    lock.lock();

    // 唤醒

    condition.signal();

    lock.unlock();

    System.out.println(Thread.currentThread().getName() + ":3");

  

}

 

 

Condition源码解读

public final void await() throws InterruptedException {

    if (Thread.interrupted())

        throw new InterruptedException();
// 将当前节点添加到最后一个节点

    Node node = addConditionWaiter();
//释放锁的状态

    long savedState = fullyRelease(node);

    int interruptMode = 0;

    while (!isOnSyncQueue(node)) {
// 如果当前线程为-2 则当前线程变为阻塞状态

        LockSupport.park(this);

        if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)

            break;

    }
//重新获取锁

    if (acquireQueued(node, savedState) && interruptMode != THROW_IE)

        interruptMode = REINTERRUPT;

    if (node.nextWaiter != null) // clean up if cancelled

        unlinkCancelledWaiters();

    if (interruptMode != 0)

        reportInterruptAfterWait(interruptMode);

}

 

public final void signal() {

    if (!isHeldExclusively())

        throw new IllegalMonitorStateException();
//获取单向链表,

    Node first = firstWaiter;

    if (first != null)

        doSignal(first);

}

condition是要和lock配合使用的也就是condition和Lock是绑定在一起的,而lock的实现原理又依赖于AQS,自然而然ConditionObject作为AQS的一个内部类无可厚非。我们知道在锁机制的实现上,AQS内部维护了一个同步队列,如果是独占式锁的话,所有获取锁失败的线程的尾插入到同步队列,同样的,condition内部也是使用同样的方式,内部维护了一个 等待队列,所有调用condition.await方法的线程会加入到等待队列中,并且线程状态转换为等待状态。另外注意到ConditionObject中有两个成员变量

 

内容太多了:这篇很详细 https://www.jianshu.com/p/730b6945bdfd

 

Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,阻塞队列实际上是使用了Condition来模拟线程间协作。

  • Condition是个接口,基本的方法就是await()和signal()方法;
  • Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
  • 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用

思考:为什么要加condition的方法,直接lock,unlock不就行了吗?

答案:https://zhuanlan.zhihu.com/p/86108783

condition的使用场景:

1. 调用condition.await方法后线程依次尾插入到等待队列中,如图队列中的线程引用依次为Thread-0,Thread-1,Thread-2....Thread-8;2. 等待队列是一个单向队列。通过我们的猜想然后进行实验验证,我们可以得出等待队列的示意图如下图所示:

 

 

每一行代码都有它的涵义,多问一句为什么;别怕,理清思路,一切代码都是数据的流动和转化,耐心一点,慢慢积累!一起加油!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值