我们要实现一个线程安全的队列有两种实现方式,阻塞算法、非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)

或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现,本节我们就来研究下

ConcurrentLinkedQueue是如何保证线程安全的同时又能高效的操作的。

一.ConcurrentLinkedQueue

当前常用的多线程同步机制可以分为下面三种类型:

  • volatile 变量:轻量级多线程同步机制,不会引起上下文切换和线程调度。仅提供内存可见性保证,不提供原子性

所以要在多线程中安全使用volatile,必须同时满足

1、对变量的写入操作不依赖其当前值(不满足:number++、count=count*5等,满足:boolean变量、记录温度变化的变量等);

2、该变量没有包含在具有其他变量的不变式中(不满足:不变式low < up)

  • CAS 原子指令:轻量级多线程同步机制,不会引起上下文切换和线程调度。它同时提供内存可见性和原子化更新保证。
  • 互斥锁:重量级多线程同步机制,可能会引起上下文切换和线程调度,它同时提供内存可见性和原子性。

ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,

它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。基于CAS的“wait-free”(无等待)来实现,CAS并不是一个

算法,它是一个CPU直接支持的硬件指令,这也就在一定程度上决定了它的平台相关性。

ConcurrentLinkedQueue 的非阻塞算法实现主要可概括为下面几点:

  • 使用 CAS 原子指令来处理对数据的并发访问,这是非阻塞算法得以实现的基础。
  • head/tail 并非总是指向队列的头 / 尾节点(???),也就是说允许队列处于不一致状态。

这个特性把入队 /出队时,原本需要一起原子化执行的两个步骤分离开来,从而缩小了入队 /出队时需要原子化更新值的范围到唯一变量。这是非阻塞算法得以实现的关键。

  • 以批处理方式来更新head/tail,从整体上减少入队 / 出队操作的开销。

二。文档说明摘要

Iterators are weakly consistent, returning elements reflecting the state of the queue at some point at or since the creation of the iterator.

They do not throw ConcurrentModificationException, and may proceed concurrently with other operations. Elements contained in the

queue since the creation of the iterator will be returned exactly once.

Beware that, unlike in most collections, the size method is NOT a constant-time operation. Because of the asynchronous nature of these

queues, determining the current number of elements requires a traversal of the elements, and so may report inaccurate results if this collection

is modified during traversal. Additionally, the bulk operations addAllremoveAllretainAllcontainsAllequals, and toArray are not

guaranteed to be performed atomically. For example, an iterator operating concurrently with an addAll operation might view only some of

the added elements.

相关内容:

锁、volatile、CAS

原文:Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析

最新文章

  1. crawler4j 学习(二)
  2. php bmp中创建图像bmp2gd,让GD支持32位BMP
  3. 利用SQL注入漏洞登录后台的实现方法
  4. Linux大神必备-文本编辑器
  5. struts 的问题是由于没有写的name有缺少的项,没有完全对应
  6. Java实现队列
  7. nginx 配置文件
  8. commands - `for`
  9. [原]基于CAS实现单点登录(SSO):登录成功后,cas client如何返回更多用户信息
  10. Cocos2dx项目移植Android平台
  11. C#使用LitJson解析JSON(转)
  12. [CQOI2013]棋盘游戏
  13. 【转】Java方向如何准备技术面试答案(汇总版)
  14. Linux时间子系统之(十六):clockevent
  15. 记录Ocelot + SignalR 多服务端测试
  16. 监控 redis 执行命令
  17. vue的生存周期
  18. 【Mac brew】代理安装brew insall
  19. 我发起了一个 .Net 平台上的 产生式编程 开源项目 GP.Net
  20. 【linux】使用swap文件恢复非正常关闭的文件

热门文章

  1. Python学习笔记18-发送邮件
  2. python中的数据类型与json的数据类型之间的转化
  3. Subversion权限详解
  4. PS合成以及分解GIF
  5. .net环境下的缓存技术-转载!
  6. IOS多线程之序
  7. 2017春季阿里大文娱(优酷)——C++研发一面
  8. 【大数据系列】节点的退役和服役[datanode,yarn]
  9. 【Spring Boot&amp;&amp;Spring Cloud系列】提高数据库访问性能
  10. canvas - drawImage()方法绘制图片不显示的问题