Lock和Condition在JDK中LinkedBlockingQueue的应用
Lock和Condition在JDK中LinkedBlockingQueue的应用,核心源码注释解析如下:
import java.util.concurrent.LinkedBlockingQueue.Node;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; /**
* LinkedBlockingQueue核心方法源码分析
*
*
*/
public class LinkedBlockingQueue { /** Current number of elements */
//使用AtomicInteger的原因是:LinkedBlockingQueue的take和put使用的是两把锁。所以需要对count进行同步。
//同时count使用AtomicInteger可以解决take和put的冲突操作
private final AtomicInteger count = new AtomicInteger(0); /** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition(); //绑定takeLock /** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition();//绑定putLock /**
* Inserts the specified element at the tail of this queue, waiting if
* necessary for space to become available.
*
* @throws InterruptedException
* {@inheritDoc}
* @throws NullPointerException
* {@inheritDoc}
*/
public void put(E e) throws InterruptedException {
if (e == null)
throw new NullPointerException();
// Note: convention in all put/take/etc is to preset local var
// holding count negative to indicate failure unless set.
int c = -1;
Node<E> node = new Node(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
/*
* Note that count is used in wait guard even though it is not
* protected by lock. This works because count can only decrease at
* this point (all other puts are shut out by lock), and we (or some
* other waiting put) are signalled if it ever changes from
* capacity. Similarly for all other uses of count in other wait
* guards.
*/
while (count.get() == capacity) {
notFull.await(); //绑定putLock
}
enqueue(node);
// 此处 c =size - 1(size为容器实际大小)
c = count.getAndIncrement();
if (c + 1 < capacity) //c+1 =size-1+1 =size ,如果c + 1 =size < capacity 的话
notFull.signal(); //唤醒其他生产者生产数据
} finally {
putLock.unlock();
}
if (c == 0) //c=size-1==0,就是size==1?如果size=1代表还有元素,通知消费者生产数据
signalNotEmpty(); //notEmpty.signal();
} /**
* Signals a waiting take. Called only from put/offer (which do not
* otherwise ordinarily lock takeLock.)
*/
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal(); //绑定takeLock
} finally {
takeLock.unlock();
}
} public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await(); //绑定takeLock
}
x = dequeue();
// 有点绕:获取当前count的值,然后减1。
c = count.getAndDecrement();
//而此时由于x = dequeue()代码消费了一个数据,所以c=size+1
if (c > 1)//当前c=size+1>1的话,则就是size>0.所以此时就是有元素的,唤醒其他消费者消费数据
notEmpty.signal(); //绑定takeLock
} finally {
takeLock.unlock();
}
if (c == capacity) //c = size +1 ==capacity 所以size =capacity-1,则容器还没有满,所以通知生产者生产数据
signalNotFull(); // 调用notFull.signal();
return x;
} /**
* Signals a waiting put. Called only from take/poll.
*/
private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal(); //绑定putLock
} finally {
putLock.unlock();
}
}
}
Lock和Condition在JDK中LinkedBlockingQueue的应用的更多相关文章
- Lock和Condition在JDK中ArrayBlockingQueue的应用
ArrayBlockingQueue的实现思路简单描述,ArrayBlockingQueue的底对于互斥访问使用的一个锁.细节参考源码take和put方法: import java.util.conc ...
- Java中的线程--Lock和Condition实现线程同步通信
随着学习的深入,我接触了更多之前没有接触到的知识,对线程间的同步通信有了更多的认识,之前已经学习过synchronized 实现线程间同步通信,今天来学习更多的--Lock,GO!!! 一.初时Loc ...
- 线程高级应用-心得5-java5线程并发库中Lock和Condition实现线程同步通讯
1.Lock相关知识介绍 好比我同时种了几块地的麦子,然后就等待收割.收割时,则是哪块先熟了,先收割哪块. 下面举一个面试题的例子来引出Lock缓存读写锁的案例,一个load()和get()方法返回值 ...
- Java并发(10)- 简单聊聊JDK中的七大阻塞队列
引言 JDK中除了上文提到的各种并发容器,还提供了丰富的阻塞队列.阻塞队列统一实现了BlockingQueue接口,BlockingQueue接口在java.util包Queue接口的基础上提供了pu ...
- 【Java线程】Lock、Condition
http://www.infoq.com/cn/articles/java-memory-model-5 深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...
- 【Java线程】锁机制:synchronized、Lock、Condition
http://www.infoq.com/cn/articles/java-memory-model-5 深入理解Java内存模型(五)——锁 http://www.ibm.com/develope ...
- 并发之lock的condition接口
13.死磕Java并发-----J.U.C之Condition 12.Condition使用总结 11.Java并发编程系列之十七:Condition接口 === 13.死磕Java并发-----J. ...
- Lock和Condition
1 什么是可重入锁 可重入锁是说一个线程在已经获取了该锁的情况下,还可以再次获取该锁. 主要的应用场景: 可重入锁指的是在一个线程中可以多次获取同一把锁,比如:一个线程在执行一个带锁的方法,该方法中又 ...
- 【Java线程】锁机制:synchronized、Lock、Condition(转)
原文地址 1.synchronized 把代码块声明为 synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility). 1.1 原子性 ...
随机推荐
- css布局------左边宽度不定,右边宽度自动填满剩余空间
HTML <div class="container"> <div class="left"></div> <div ...
- Numbers、Strings、Lists 笔记<一>
下一篇:流程控制<二> 阅读链接:官方Python3.7教程 废话:最近开始阅读python3.7文档,希望把容易混淆的知识记下来. 除法总是返回一个浮点数 >>> 8/ ...
- IEnumerable、ICollection、IList、List之间的区别与方法介绍
区别 以下列出IEnumerable.ICollection.IList.List继承关系.(这里带有泛型,非泛型也是一样的关系) IEnumerable<T>: public inter ...
- nginx跳转访问
server { listen 8888; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; ...
- HDU6215
Brute Force Sorting Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Othe ...
- MAC MYSQ忘记密码重置方法
网友的方法,记个笔记请勿转载. step1: 关闭mysql服务: 苹果->系统偏好设置->最下边点mysql 在弹出页面中 关闭mysql服务(点击stop mysql server) ...
- spring boot 随手记
1.当加入security 起步依赖后,如果不做任何手动配置的话,默认会跳转到一个登录页面,不管你喜不喜欢,所有的请求都必须登录,用户名和密码是保存在内存中的, 默认用户名是user 密码在控制台里 ...
- 学习css(TODO)
1. css 是一个什么样的角色? 答:css 负责控制网页的样式. 扩展:div + css 是经典的网页布局.实现网页内容与表现相分离. 2. css 的使用方式? 答:1. 内联式:直接在 HT ...
- Hbase简单配置与使用
一. HBase的 二.基于Hadoop的HBase架构 HBase内置有zookeeper,但一般我们会有其他的Zookeeper集群来监管master和regionserver,Zookeeper ...
- spring 开发 Tars
和不使用 Spring 的 tars HelloWord 项目相比,客户端完全一样,服务端两个地方不一样 创建不使用 Spring 的 tars HelloWord 步骤: https://www.c ...