类图概述

由类图可以看出,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. 计算机网络复习小结(3)-IPv4

    IPv4分组 一个IP分组由首部和数据两部分组成,首部前一部分的长度固定,共20B,是所有IP分组必须具有的.在IP数据报首部中有三个关于长度的标记,一个是首部长度,一个是总长度,一个是片偏移,基本单 ...

  2. Redis Stream实现全部节点机器推送消息

    背景 有时候,在微服务时代,我们需要对全部的机器节点进行通知.在常规情况下,一个请求经过负载均衡只有一个机器可以收到.那么,如何能让全部的机器都收到同样的请求呢?需要借助消息队列的监听机制,让每个节点 ...

  3. python——NLP关键词提取

    关键词提取顾名思义就是将一个文档中的内容用几个关键词描述出来,这样这几个关键词就可以提供这个文档的大部分信息,从而提高信息获取效率. 关键词提取方法同样分为有监督和无监督两类,有监督的方法比如构造一个 ...

  4. iOS 制作本地库Development Pods

    1.cd到指定的路径文件夹下 ,创建本地库,如:pod lib create XXNetworking 2.删除Classes文件下的ReplaceMe文件,添加自己的类. 3.修改XXNetwork ...

  5. react+antd 开发一个可动态增减的复合组件

    需求如图: 与后端协商好的表单数据为: 组件代码: /* 阶梯分成组件 */ import React, { useState, useEffect } from 'react'; import { ...

  6. Linux挂载tf卡空间

    https://blog.csdn.net/cao849861802/article/details/126039190

  7. react实现某个元素节点截图(html2canvas)

    1.安装所需插件:html2canvas: 2.引入插件: import html2canvas from 'html2canvas'; 3.使用: const creatImg = () => ...

  8. 【python】第一模块 步骤五 第二课、Python多线程

    第二课.Python多线程 一.课程介绍 1.1 课程概要 章节概要 进程.线程与并发 对多核的利用 实现一个线程 线程之间的通信 线程的调度和优化 1.2 为什么要学习多线程 (线程)使用场景 快速 ...

  9. [杂谈吐槽]UE国内社区环境

    此篇博客是我个人想法,当然也是不争的事实,如果您有意见,那您也是我说那些人其中的一员. --此部分为社区环境差最恶劣的原因-- 国内的虚幻社区环境可以说不能再烂了,虚幻商城和虚幻引擎的蓝图是非常强大的 ...

  10. Python中使用pyyaml对yaml文件进行读写删操作

    安装库 pip install pyyaml 读取yaml/yam格式的文件 def get_yaml(filepath) -> list: """ :param ...