看了下网上关于链表的无锁操作,写的不清楚,遂自己整理一部分,主要使用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)的更多相关文章

  1. Atitit。Cas机制 软件开发 编程语言 无锁机制 java c# php

    Atitit.Cas机制 软件开发 编程语言 无锁机制 java c# php 1. 为什么需要无锁操作1 2. 硬件支持 cas  atomic2 3. 无锁编程(Lock-Free)就是在某些应用 ...

  2. 聊聊高并发(三十二)实现一个基于链表的无锁Set集合

    Set表示一种没有反复元素的集合类,在JDK里面有HashSet的实现,底层是基于HashMap来实现的.这里实现一个简化版本号的Set,有下面约束: 1. 基于链表实现.链表节点依照对象的hashC ...

  3. 无锁同步-JAVA之Volatile、Atomic和CAS

    1.概要 本文是无锁同步系列文章的第二篇,主要探讨JAVA中的原子操作,以及如何进行无锁同步. 关于JAVA中的原子操作,我们很容易想到的是Volatile变量.java.util.concurren ...

  4. CAS无锁操作

    https://coolshell.cn/articles/8239.html 主要讲的是<Implementing Lock-Free Queues>的论点,具体直接看论文最好.这里总结 ...

  5. 【Java并发编程】9、非阻塞同步算法与CAS(Compare and Swap)无锁算法

    转自:http://www.cnblogs.com/Mainz/p/3546347.html?utm_source=tuicool&utm_medium=referral 锁(lock)的代价 ...

  6. (转载)java高并发:CAS无锁原理及广泛应用

    java高并发:CAS无锁原理及广泛应用   版权声明:本文为博主原创文章,未经博主允许不得转载,转载请注明出处. 博主博客地址是 http://blog.csdn.net/liubenlong007 ...

  7. 非阻塞同步算法与CAS(Compare and Swap)无锁算法

    锁(lock)的代价 锁是用来做并发最简单的方式,当然其代价也是最高的.内核态的锁的时候需要操作系统进行一次上下文切换,加锁.释放锁会导致比较多的上下文切换和调度延时,等待锁的线程会被挂起直至锁释放. ...

  8. boost 无锁队列

    一哥们翻译的boost的无锁队列的官方文档 原文地址:http://blog.csdn.net/great3779/article/details/8765103 Boost_1_53_0终于迎来了久 ...

  9. DIOCP开源项目-Delphi高性能无锁队列(lock-free)

    最近想在DIOCP中加入任务调度线程,DIOCP的工作线程作为生产者(producer)将接受到的数据对象,投递到任务调度线程中,然后统一进行分配.然而这一切都需要一个队列, 这几天都在关注无锁队列. ...

随机推荐

  1. django的模型类管理器-----------数据库操作的封装

    模型实例方法 str():在将对象转换成字符串时会被调用. save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句. delete():将模型对象从数据表中删除 ...

  2. mybatis批量插入

    <insert id="insertBatch" parameterType="java.util.List" > insert into biz_ ...

  3. Hibernat 原生SQL运行结果集处理方法

    hibernate对原生SQL查询执行的控制是通过SQLQuery接口进行的. Session.createSQLQuery(); 使用list()方法可以把Session.createSQLQuer ...

  4. www的构建技术

    www的构建技术分别是: html超文本标记语言,页面的文本显示 http超文本传输协议,信息传输转移的约定 url统一资源定位符,客户端浏览超文本的地址集合

  5. Vue项目模板--和--webpack自动化构建工具的---项目打包压缩使用

    [首先安装node.js]: 1. 从node.js官网下载并安装node,安装过程很简单. 2. npm 版本需要大于 3.0,如果低于此版本需要升级它: # 查看版本 npm -v2.3.0 #升 ...

  6. 1020关于MYCAT的安装和使用总结

    第一部分 读写分离配置 转自:http://www.51testing.com/html/34/369434-3686088.html 使用Mycat 做简单的读写分离(一) 原本使用的是amoeba ...

  7. linux搭建node环境超详细教程

    linux 环境搭建详细步骤 1.访问官方网址:https://nodejs.org/en/download/ 2.选择和你服务器版本相关的压缩包,复制下载链接 3.服务器登录ssh,(这里我用的服务 ...

  8. 技巧:如何提升Oracle用户密码的安全性

    环境:Oracle 11.2.0.4 客户需求:主要背景是数据库中有很多业务用户名,且由于部分用户缺乏安全意识,甚至直接将自己的密码设置为和用户名一样,目前客户期望密码设置不要过于简单,最起码别和用户 ...

  9. [bzoj 1293] [SCOI2009] 生日礼物

    传送门(bzoj) 传送门(luogu) 题目: Description 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应 ...

  10. java中的引用传递问题

    ---恢复内容开始--- 第一个引用传递案例: class Message{ private int num; public Message(int num){ this.num=num; } pub ...