当前位置:网站首页>JUC并发容器——ConcurrentLinkedQueue
JUC并发容器——ConcurrentLinkedQueue
2022-08-04 05:32:00 【real沛林】
线程安全的队列
- 阻塞队列:使用一个锁(进队和出队同一个锁)和两个锁(入队和出队用不同的锁)
- 非阻塞队列:ConcurrentLinkedQueue
ConcurrentLinkedQueue特性:
- 是一个基于链接节点的无界线程安全队列,
- 按先进先出的插入顺序进行排序,
- 采用“wait-free”算法(CAS算法)实现,
- 具体实现:添加元素时它会添加到队列尾部;获取元素时,它会返回队列头部的元素。
1.8 source code
https://blog.csdn.net/chenssy/article/details/74853120
1、入队方法
public boolean offer(E e) {
//判断入队节点是否为空
checkNotNull(e);
//构造入队节点
final Node<E> newNode = new Node<E>(e);
//死循环,入队不成功继续入队
//p初始为tail
for (Node<E> t = tail, p = t;;) {
//q为p的后继,若p为队尾,则q为空,若p不是队尾,则有其他线程更改了队列
Node<E> q = p.next;
if (q == null) {
//p是队尾 将入队节点变成队尾的后继
if (p.casNext(null, newNode)) {
//判断tail节点是否为尾节点
if (p != t)
//如果不是,将入队节点修改为队尾
casTail(t, newNode);
return true;
}
// Lost CAS race to another thread; re-read next
}
//说明这个节点已经被移除了
else if (p == q)
//如果队尾未发生改变,t还是队尾,则将p指向t,继续插入新节点
//如果队尾发生改变,则将p指向队头重新开始插入新节点
p = (t != (t = tail)) ? t : head;
else
//说明p有后继,p的后继才是队尾,则需要将p指向队尾
p = (p != t && t != (t = tail)) ? t : q;
}
}
入队方法个人感觉还是挺复杂的。大致步骤如下
1、构造新节点
2、开始循环,p表示队尾,默认p初始为tail,
3、如果p后继为空,说明p就是tail,则插入新节点返回
4、如果p节点被删除,则需要重新赋值p,如果tail未变,则将p赋值为t,如果tail改变,则将p赋值为队头,继续插入
5、如果p有后继,说明p不是tail,则需要将p指向tail。
2出队方法
public E poll() {
restartFromHead:
//死循环
for (;;) {
for (Node<E> h = head, p = h, q;;) {
//取出队头的值
E item = p.item;
//如果队头值不为空则将队头的值更新为空
if (item != null && p.casItem(item, null)) {
//判断p是否等于head,如果不等于则重新指向队头
if (p != h)
updateHead(h, ((q = p.next) != null) ? q : p);
return item;
}
//队列为空
else if ((q = p.next) == null) {
updateHead(h, p);
return null;
}
//有其他线程将队头的值出队了,则重新开始出队
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}
出队的大致步骤如下:
1、h等于head,p初始化为head
2、取出队头的值
3、如果队头的值不为空,则将队头的值置空,然后判断head是否变化,如果变化重新寻找head,返回队头的值
4、如果队列为空,则需要重新寻找队头,返回null
5、如果有其他线程将队头的值出队了,那么重新从最新head开始出队
边栏推荐
猜你喜欢
随机推荐
Chapter One Introduction
【HIT-SC-MEMO6】哈工大2022软件构造 复习笔记6
LeetCode_Nov_4th_Week
2020-03-27
IDEA创建Servlet步骤
IDEA中创建web项目实现步骤
EL表达式
Cut the hit pro subtitles export of essays
Miscellaneous [development] [VS Code] remote - SSD retry failed
jdbc:mysql://localhost:3306/student?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8时报错
MVC自定义配置
实现高并发服务器(二)
Copy Siege Lion's Annual "Battle" | Review 2020
安装MySQL的详细步骤
Golang environment variable settings (2)--GOMODULE & GOPROXY
arm学习-1-开发板
基于Webrtc和Janus的多人视频会议系统开发7 - publish和subscribe声音设备冲突导致对方听不到声音
arm learning-1-development board
[Daily Office][Miscellaneous][vscode]tab space
Deep learning, "grain and grass" first--On the way to obtain data sets