跟我学代码架构设计模式之--Lock和Condition

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w1857518575/article/details/85263858

# Condition和JDK中的Object类的wait、notify方法一样是控制线程状态的,使用Condition的前提也是必须要先获得锁对象。

# 之前的博文分析过锁,这里先来总结下锁释放的几种方式:

1 调用锁的unlock等方法手动释放锁

2 线程异常退出的时候虚拟机自动释放锁(有些锁可能不会自动释放)

3 调用Condition类的await来使线程等待并释放锁

由于使用Condition使用前必须获得锁,所以我们可以在语义上得出锁和条件的使用场景:

锁实现的语义:是线程得不到锁的时候进入阻塞(tryLock等方法不会阻塞,而是放弃获得锁);

条件实现的语义是:在线程获得锁的时候因为某些条件达不到要求而必须放弃锁然后进入条件对象的阻塞队列中等待条件满足;

下面举一个经典的生产者消费者的例子:

角色:一个固定容量的队列,多个生产者线程和多个消费者线程

需求:队列做为受保护的资源,要求同一时刻只能有一个生产者向其中写入数据,只能有一个消费者从队列消费数据。

实现:

首先我们要有一把写锁来保证同一时刻只有一个生产者写数据;一把读锁保证同一时刻只有一个消费者消费数据;

如果不加Condition:

生产者的代码实现是:1先获得写锁 2如果队列满了就不写数据直接释放锁 3 如果队列不满就写数据,然后释放锁

消费者的代码实现是:  1先获得读锁 2 如果队列为空就不消费数据直接释放锁 3 如果队列不空就消费一个数据然后释放锁

弊端:考虑下面的两种情况:

1 队列满了,消费者消费的不及时,这样就会导致多个生产者线程频繁的轮流获得锁、释放锁、挂起线程,CPU时间全都浪费在线程上下文切换上面了

2 队列空,生产者生产不及时,这样会导致多个消费者线程频繁的进行上下文切换

如果加上Condition:

生产者的代码实现是:0 构建一个写条件对象  1先获得写锁 2如果队列满了就await在写条件对象上(同时会释放锁) 3 如果队列不满就写数据,然后notify读条件对象来唤醒消费者消费数据,然后释放锁

消费者的代码实现是:  0 构建一个读条件对象  1先获得读锁 2 如果队列为空就await在读条件对象上(同时会释放锁) 3 如果队列不空就消费一个数据,然后notify写条件对象来唤醒生产者生产数据,然后释放锁

读条件和写条件肯定不会同时不成立,即:肯定不会所有的生产者和消费者线程都阻塞的死锁现象出现

好处:

1 队列满了,消费者消费的不及时,生产者线程就会等待在写条件对象上,不会产生不必要的线程上下文切换

2 队列空,生产者生产不及时,消费者线程就会等待在读条件对象上,也不会产生不必要的线程上下文切换

(完)

猜你喜欢

转载自blog.csdn.net/w1857518575/article/details/85263858