多线程六-线程通信之Condition使用与设计猜想

海上生明月,天涯共此时。愿大家在这个团圆的夜晚,收获满满的温馨和喜悦,团圆美满,中秋快乐!
月满中秋

使用示例

ConditionDemoAwait :开始之后加锁,阻塞并释放锁

package com.caozz.demo5.concurrent;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class ConditionDemoAwait implements Runnable{

    private Lock lock;

    private Condition condition;

    public ConditionDemoAwait(Lock lock, Condition condition){
        this.condition = condition;
        this.lock = lock;
    }

    @Override
    public void run() {
        System.out.println("begin---ConditoiopnDemoAwait--");
        lock.lock();
        try{
            condition.await();
            System.out.println("end---ConditoiopnDemoAwait--");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

  • ConditionDemoSinal :开始之后唤醒,此时并不会释放锁,所以会先结束,才会释放锁
package com.caozz.demo5.concurrent;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class ConditionDemoSinal implements Runnable{

    private Lock lock;

    private Condition condition;

    public ConditionDemoSinal(Lock lock, Condition condition){
        this.condition = condition;
        this.lock = lock;
    }

    @Override
    public void run() {
        System.out.println("begin---ConditoiopnDemoSinal--");
        lock.lock();
        try{
            //让当前线程阻塞,相当于Object.notify()
            condition.signal();
            System.out.println("end---ConditoiopnDemoSinal--");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

测试:

package com.caozz.demo5.controller;

import com.caozz.demo5.concurrent.ConditionDemoAwait;
import com.caozz.demo5.concurrent.ConditionDemoSinal;
import com.caozz.demo5.concurrent.Consumer;
import com.caozz.demo5.concurrent.Producer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        ConditionDemoAwait await = new ConditionDemoAwait(lock, condition);
        ConditionDemoSinal sinal = new ConditionDemoSinal(lock, condition);
        new Thread(await).start();
        Thread.sleep(10);
        new Thread(sinal).start();
    }
}

结果:
线程启动:await启动,执行开始后加锁,并阻塞,此时signal开始,并执行唤醒,然后signal结束,释放锁,被唤醒得await结束
如果启动不加sleep,可能会sinal先启动,那么sinal开始,唤醒,结束,然后await执行,阻塞,然后就会一直阻塞,无法结束,因为没有被唤醒

begin---ConditoiopnDemoAwait--
begin---ConditoiopnDemoSinal--
end---ConditoiopnDemoSinal--
end---ConditoiopnDemoAwait--

设计猜想

  • 作用:实现线程的阻塞与唤醒
  • 前提条件: 必须先要获得锁
  • await、signal、signalall
    • await:让线程阻塞,并且释放锁
    • signal:唤醒阻塞的线程

  • 加锁的操作,必然会涉及到AQS的阻塞队列
  • await释放锁时,AQS队列中不存在已经释放锁的线程,那么被释放的线程去到了哪里?
  • 唤醒被阻塞的线程:被阻塞的线程在哪里?
    经过上面的思考,应该可以想到,通过await方法释放的线程,必须要有一个地方来存储,同时,阻塞的线程,是通过AQS还是单独地方来存储呢?

Condition等价于wait/notify
Condition是JUC里面得实现,所以不能使用wait/notify ,锁的实现不同。

欢迎大家留言,以便于后面的人更快解决问题!另外亦欢迎大家可以关注我的微信公众号,方便利用零碎时间互相交流。共勉!

posted @ 2024-09-16 11:01  东方欲晓_莫道君行早  阅读(8)  评论(0编辑  收藏  举报