链表的无锁操作 (JAVA)
看了下网上关于链表的无锁操作,写的不清楚,遂自己整理一部分,主要使用concurrent并发包的CAS操作。
1. 链表尾部插入
待插入的节点为:cur
尾节点:pred
基本插入方法:
do{
pred = find_tail(); //重新找尾节点
}(! pred.next.compareAndSet(NULL, cur)) //pred.next 是否为NULL,是则将其指向cur,不是则有新的节点插入
这种插入方法是不带标记的,如果不涉及链表删除这个方法是可行的。
但是如果有删除操作,pred节点可能会被删除,所以我们需要再加入一个标记位判断pred是否被删除(false 未删除)
do{
pred = find_tail();
}(! pred.next.compareAndSet(NULL, cur, false, false)); //检查pred.next是被否标记为false,并标记为false
因为我们插入是对pred.next进行CAS操作,所以虽然要判断pred是否被删除,我们却只能看它的next域的标记,所以在删除的时候要和这里配合置next位为true让本次添加不成功
注意这里的next的置位与否不是next节点的,是pred本身的,因为只能从pred自己看到是否被删除,所以节点的数据结构不包含flag,节点的next域包含flag,这种结构具体参考AtomicMarkableReference
这里如果先判断pred是否为false是不行的,所有操作必须在CAS中完成,因为判断的一瞬间是OK的但是不代表执行CAS的时候也是OK的
(TIP:因为是队尾,next域是NULL,但是仍然含有标记位,每个新node尾节点添加的时候都是node.next = new AtomicMarkableReference<Node>(null,false))
2. 链表删除节点
待删除的节点为:cur
do{
succ = cur.next; //重新找next节点
if (cur.next == true) break; //有线程已经将其逻辑删除
pred = pred(cur); //找pred节点
flag1 = cur.next.compareAndSet(succ, succ, false, true); //第一个CAS将cur.next置为true,防止添加操作和重复删除操作
if (! flag1) continue;
flag2 = pred.next.compareAndSet(cur, succ, false, false); //第二个CAS将pred.next指向succ,并将succ的为置为false
if(! flag2) continue;
}(0);
这里两次CAS操作,第一次置位,也就是所谓的逻辑删除,和添加节点相呼应,这里标记完了之后在第二个CAS执行前,往本节点之后的添加都不成功
本次CAS失败说明有其它线程的删除操作或CAS之前有往cur的next有添加操作(succ改变),返回再次尝试
第二次则将原来指向cur的pred.next指向succ,进行物理删除,这里succ已经不能改变了,因为第一次CAS成功之后next置位其他线程既不能添加也不能删除
但是pred可以被删除,pred被删除之后导致pred.next置位,这次CAS失败。
这里第二次CAS操作可能其他地方也有相同的代码,如果本线程在第一次CAS调用完后阻塞,可以让其他线程看到这个标记后帮忙进行节点删除和清置位,这也是wait free的设计的核心思想
3. 链表某节点插入
实现原理相同,不多赘述,一定要注意和删除的判断过程是保证自洽的。
链表的无锁操作 (JAVA)的更多相关文章
- Atitit。Cas机制 软件开发 编程语言 无锁机制 java c# php
Atitit.Cas机制 软件开发 编程语言 无锁机制 java c# php 1. 为什么需要无锁操作1 2. 硬件支持 cas atomic2 3. 无锁编程(Lock-Free)就是在某些应用 ...
- 聊聊高并发(三十二)实现一个基于链表的无锁Set集合
Set表示一种没有反复元素的集合类,在JDK里面有HashSet的实现,底层是基于HashMap来实现的.这里实现一个简化版本号的Set,有下面约束: 1. 基于链表实现.链表节点依照对象的hashC ...
- 无锁同步-JAVA之Volatile、Atomic和CAS
1.概要 本文是无锁同步系列文章的第二篇,主要探讨JAVA中的原子操作,以及如何进行无锁同步. 关于JAVA中的原子操作,我们很容易想到的是Volatile变量.java.util.concurren ...
- CAS无锁操作
https://coolshell.cn/articles/8239.html 主要讲的是<Implementing Lock-Free Queues>的论点,具体直接看论文最好.这里总结 ...
- 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法
转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...
- (转载)java高并发:CAS无锁原理及广泛应用
java高并发:CAS无锁原理及广泛应用 版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...
- 非阻塞同步算法与CAS(Compare and Swap)无锁算法
锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...
- boost 无锁队列
一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...
- DIOCP开源项目-Delphi高性能无锁队列(lock-free)
最近想在DIOCP中加入任务调度线程,DIOCP的工作线程作为生产者(producer)将接受到的数据对象,投递到任务调度线程中,然后统一进行分配.然而这一切都需要一个队列, 这几天都在关注无锁队列. ...
随机推荐
- django的模型类管理器-----------数据库操作的封装
模型实例方法 str():在将对象转换成字符串时会被调用. save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句. delete():将模型对象从数据表中删除 ...
- mybatis批量插入
<insert id="insertBatch" parameterType="java.util.List" > insert into biz_ ...
- Hibernat 原生SQL运行结果集处理方法
hibernate对原生SQL查询执行的控制是通过SQLQuery接口进行的. Session.createSQLQuery(); 使用list()方法可以把Session.createSQLQuer ...
- www的构建技术
www的构建技术分别是: html超文本标记语言,页面的文本显示 http超文本传输协议,信息传输转移的约定 url统一资源定位符,客户端浏览超文本的地址集合
- Vue项目模板--和--webpack自动化构建工具的---项目打包压缩使用
[首先安装node.js]: 1. 从node.js官网下载并安装node,安装过程很简单. 2. npm 版本需要大于 3.0,如果低于此版本需要升级它: # 查看版本 npm -v2.3.0 #升 ...
- 1020关于MYCAT的安装和使用总结
第一部分 读写分离配置 转自:http://www.51testing.com/html/34/369434-3686088.html 使用Mycat 做简单的读写分离(一) 原本使用的是amoeba ...
- linux搭建node环境超详细教程
linux 环境搭建详细步骤 1.访问官方网址:https://nodejs.org/en/download/ 2.选择和你服务器版本相关的压缩包,复制下载链接 3.服务器登录ssh,(这里我用的服务 ...
- 技巧:如何提升Oracle用户密码的安全性
环境:Oracle 11.2.0.4 客户需求:主要背景是数据库中有很多业务用户名,且由于部分用户缺乏安全意识,甚至直接将自己的密码设置为和用户名一样,目前客户期望密码设置不要过于简单,最起码别和用户 ...
- [bzoj 1293] [SCOI2009] 生日礼物
传送门(bzoj) 传送门(luogu) 题目: Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应 ...
- java中的引用传递问题
---恢复内容开始--- 第一个引用传递案例: class Message{ private int num; public Message(int num){ this.num=num; } pub ...