类图概述

由类图可以看出,L是单向链表实现的,有两个ReentrantLock实例用来控制元素入队和出队的原子性,takeLock用来控制只有一个线程可以从队头获取元素,putLock控制只有一个线程可以从队尾添加元素。notEmpty和notFull是条件变量,内部有条件队列用来存放进队和出队被阻塞的线程。

阻塞入队

put操作:在队尾插入元素,如果队列已满则阻塞当前线程,直到队列有空闲插入成功后返回。如果在阻塞时被其他线程设置中断标志,线程会抛出异常而返回。(中断是一种线程协作的方式)

public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
final int c;
final Node<E> node = new Node<E>(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) { (3)
notFull.await();
}
enqueue(node); (4)
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}

代码(3)如果队列满了,调用await放入条件队列,当前线程被阻塞挂起后会释放获取到的putLock锁,所以其他线程就有机会获取到putLock锁了。

另外,在判断队列是否为空时为何使用while而不是if?这是考虑当前线程被虚假唤醒的问题,如果使用if语句,那么虚假唤醒后会执行(4)的入队操作,并且递增计数器,而这时候队列已经满了,从而导致队列元素溢出。而使用while循环时,假如await被虚假唤醒了,那么在此循环检查当前队列是否已满,如果是则在此进行等待。

虚假唤醒:多个等待线程在满足if条件时都会被唤醒(虚假的),但实际上条件并不满足,生产者生产出来的消费品已经被第一个线程消费了。

结论:对条件变量的状态进行不断检查直到其满足条件。

https://www.cnblogs.com/tqyysm/articles/9765667.html

阻塞出队

take操作:当线程获取到锁,其他调用take or poll的线程会被阻塞挂起(ReentrantLock内部的AQS)。如果队列为空,将当前线程放入条件队列中。

Reference

《Java并发编程之美》

LinkedBlockingQueue出入队实现原理的更多相关文章

  1. React直出实现与原理

    前一篇文章我们介绍了虚拟DOM的实现与原理,这篇文章我们来讲讲React的直出. 比起MVVM,React比较容易实现直出,那么React的直出是如何实现,有什么值得我们学习的呢? 为什么MVVM不能 ...

  2. MySQL 页完全指南——浅入深出页的原理

    之前写了一些关于 MySQL 的 InnoDB 存储引擎的文章,里面好几次都提到了页(Pages)这个概念,但是都只是简要的提了一下.例如之前在聊 InnoDB内存结构 时提到过,但当时的重点是内存架 ...

  3. 使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

    环境:Core:3.1的项目 说明:由于该方案为个人测试项目,重启时队列中的部分数据很可能会丢失, 对数据有要求的该方案不适用,不能照搬需要持久化处理, 另外发布到Linux Docker中通常不会自 ...

  4. 源代码解读Cas实现单点登出(single sign out)功能实现原理--转

    关于Cas实现单点登入(single sing on)功能的文章在网上介绍的比较多,想必大家多多少少都已经有所了解,在此就不再做具体介绍.如果不清楚的,那只能等我把single sign on这块整理 ...

  5. PHP 弹出文件下载 原理 代码

    /** * @author      default7<default7@zbphp.com> * @description 演示PHP弹出下载的原理 * * @param $file_n ...

  6. Java同步数据结构之LinkedBlockingQueue

    前言 比起ArrayBlockingQueue,LinkedBlockingQueue应该是最被大家常用的阻塞队列,LinkedBlockingQueue是基于链表的一种可选容量的阻塞队列,也就是说, ...

  7. 11.并发包阻塞队列之LinkedBlockingQueue

    在上文<10.并发包阻塞队列之ArrayBlockingQueue>中简要解析了ArrayBlockingQueue部分源码,在本文中同样要介绍的是Java并发包中的阻塞队列LinkedB ...

  8. 并发队列 – 有界阻塞队列 ArrayBlockingQueue 原理探究

    一.ArrayBlockingQueue类图结构 如图ArrayBlockingQueue内部有个数组items用来存放队列元素,putindex下标标示入队元素下标,takeIndex是出队下标,c ...

  9. Go语言GC实现原理及源码分析

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/475 本文使用的 Go 的源码1.15.7 介绍 三色标记法 三色标 ...

  10. 面试侃集合 | LinkedBlockingQueue篇

    面试官:好了,聊完了ArrayBlockingQueue,我们接着说说LinkedBlockingQueue吧 Hydra:还真是不给人喘口气的机会,LinkedBlockingQueue是一个基于链 ...

随机推荐

  1. Spring学习记事本

    原因:原因:Application的启动类不能放在默认的java目录,必须放在建有包的目录下.

  2. git 代码托管常用代码

    一.git全局账号登录 (1)全局登录账号和密码 git config --global user.name "xxx" git config --global user.emai ...

  3. UNIT TWO

    声明 基于8086的寄存器共14个16位的,分别是 ax  bx  cx  dx  (通用寄存器) si  di  bp  sp    (基址与变址寄存器) cs  ss  ds  es   (段寄存 ...

  4. Linux 同步分发脚本

    shell 内容 #!/bin/bash #1. 判断参数个数 if [ $# -lt 1 ] then echo Not Enough Arguement! exit; fi 尚硅谷大数据技术之 H ...

  5. Vue Element使用第三方图标(iconfont阿里矢量图标库)

    在  www.iconfont.cn 中搜索图标并加入购物车然后添加至项目,编辑项目名称 然后将项目下载至本地解压后将如下文件复制移到到  src/assets/icon中, 并把iconfont.c ...

  6. ESP32(WeMos D1 R32)开发资料

    1.乐鑫官网 2.ESP32踩坑 ESP32控制摇杆,定义sw的引脚时一定要设置为上拉才行. 3.ESP32入门之arduino IDE环境搭建 4.ESP32 MicroPython编程官网文档 E ...

  7. 弹框tabel

    <el-dialog title="删除数据类型" :visible.sync="isDataType" width="60%" :b ...

  8. Crypto入门 (四)不仅仅是Morse(Morse+Bacon)

    前言: 前面我们刚刚学过了解Morsecode,现在我们将继续学习 不仅仅是Morse: 题目:--/.-/-.--/..--.-/-..././..--.-/..../.-/...-/./..--. ...

  9. NFS只能挂载为nobody的解决办法

    方法一 mount中指定参数 mount -t nfs -o vers=3 192.168.23.23:/data1 /data1 这种方法不推荐,但可以解决临时挂载的需求 方法二 cat /etc/ ...

  10. MATLAB画图自动确定坐标范围(GUI)

    今天在用MATLAB做我的毕设的时候碰到一个很纠结的问题,之所以说纠结是因为我觉得这个问题很简单,可是一时半会就是弄不出来(ー`´ー).鼓捣了半个小时左右吧,终于搞出来了.下面做个纪念: 问题描述 在 ...