目标:利用AtomicStampedReference实现栈的压入弹出无锁编程

AtomicStampedReference

意义:对数据进行CAS(compareAndSet)无锁自加或者更换栈的表头之类的问题时会出现ABA问题,AtomicStampedReference通过增加版本号(时间戳)来解决这个问题。

  • AtomicStampedReference(V initialRef, int initialStamp):初始化,传入初始数据与初始版本号
  • getReference():获取当前引用数据
  • getStamp():获取当前版本号
  • set(V newReference, int newStamp):设置引用数据与版本号
  • attemptStamp(V expectedReference, int newStamp):如果当前引用等于expectedReference,就更新版本号到newStamp。主要用于无障碍编程(ObstructionFree)。
  • compareAndSet :比较数据与版本号,符合则更新数据返回true,否则返回false。
    (V expectedReference, // 当前引用数据
    V newReference, // 修改后的数据
    int expectedStamp, // 当前版本号
    int newStamp) // 修改后的版本号

代码实现:

package com.miracle.study.queue;import org.junit.jupiter.api.Test;
import org.w3c.dom.Node;import java.util.concurrent.atomic.AtomicStampedReference;/*** @author Miracle* @date 2021/4/17 16:53*/
public class LockFreeStack<T> {/*** 头部节点*/private AtomicStampedReference<Node<T>> head;/*** 初始化头部*/public LockFreeStack() {// 创建空节点var headNode = new Node<T>(null);// 将空节点作为头部并传入版本号head = new AtomicStampedReference<>(headNode, 0);}/*** 节点定义** @param <T>*/static class Node<T> {/*** 当前节点数据*/private T data;/*** 指向下一个节点*/private Node<T> next;public Node(T t) {this.data = t;}public T get() {return data;}}/*** 采用头加法* @param t*/public void push(T t) {// 创建新节点var newNode = new Node<>(t);while (true) {// 获取当前头的版本号var stamp = head.getStamp();// 获取当前头的节点var nowHead = head.getReference();// 将新节点指向头部newNode.next = nowHead;// 尝试进行修改头部,版本号+1,成功就返回,失败就重新尝试修改if (head.compareAndSet(nowHead, newNode, stamp, stamp + 1)) {return;}}}/*** 采用头删法* @return*/public T pop() {while (true) {// 获取当前头的版本号var stamp = head.getStamp();// 获取当前头的节点var nowHead = head.getReference();// 判断当前节点是否为空if (nowHead == null) {return null;}// 尝试修改当前头节点,修改成功版本号+1,修改失败重新循环尝试if (head.compareAndSet(nowHead, nowHead.next, stamp, stamp + 1)) {return nowHead.get();}}}/*** 单线程测试*/@Testpublic void singleTest() {var stack = new LockFreeStack<Integer>();for (int i = 0; i < 100; i++) {stack.push(i);}Integer j = null;while ((j = stack.pop()) != null) {System.out.println(j);}}/*** 多线程测试* @throws InterruptedException*/@Testpublic void multiTest() throws InterruptedException {var stack = new LockFreeStack<Integer>();for (int i = 0; i < 30; i++) {new Thread(() -> {for (int j = 0; j < 1000; j++) {stack.push(j);}}).start();}Thread.sleep(5000);Integer j = 0;while ((stack.pop()) != null) {j++;}System.out.println(j);}
}

Java并发练习:无锁编程相关推荐

  1. Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

    Java并发问题–乐观锁与悲观锁以及乐观锁的一种实现方式-CAS </h1><div class="clear"></div><div c ...

  2. 【翻译】RUST无锁编程

    本文内容译自Lock-freedom without garbage collection,中间有少量自己的修改. 人们普遍认为,垃圾收集的一个优点是易于构建高性能的无锁数据结构.对这些数据结构进行手 ...

  3. 无锁编程(Lock Free)框架 系列文章

    无锁编程(Lock Free)框架 系列文章: 1 前置知识:伪共享 原理 & 实战 2 disruptor 使用和原理 图解 3 akka 使用和原理 图解 4 camel 使用和 原理 图 ...

  4. 【C++】多线程与原子操作和无锁编程【五】

    [C++]多线程与原子操作和无锁编程[五] 1.何为原子操作 前面介绍了多线程间是通过互斥锁与条件变量来保证共享数据的同步的,互斥锁主要是针对过程加锁来实现对共享资源的排他性访问.很多时候,对共享资源 ...

  5. java并发框架支持锁包括,tip/面试题_并发与多线程.md at master · 171437912/tip · GitHub...

    01. java用()机制实现了进程之间的同步执行 A. 监视器 B. 虚拟机 C. 多个CPU D. 异步调用 正解: A 解析: 监视器机制即锁机制 02. 线程安全的map在JDK 1.5及其更 ...

  6. 我是如何一步步的在并行编程中将lock锁次数降到最低实现无锁编程

    在并行编程中,经常会遇到多线程间操作共享集合的问题,很多时候大家都很难逃避这个问题做到一种无锁编程状态,你也知道一旦给共享集合套上lock之后,并发和伸缩能力往往会造成很大影响,这篇就来谈谈如何尽可能 ...

  7. 帖子如何实现显示浏览次数_我是如何一步步的在并行编程中将lock锁次数降到最低实现无锁编程...

    在并行编程中,经常会遇到多线程间操作共享集合的问题,很多时候大家都很难逃避这个问题做到一种无锁编程状态,你也知道一旦给共享集合套上lock之后,并发和伸缩能力往往会造成很大影响,这篇就来谈谈如何尽可能 ...

  8. 浅谈Linux内核无锁编程原理

    非阻塞型同步 (Non-blocking Synchronization) 简介 如何正确有效的保护共享数据是编写并行程序必须面临的一个难题,通常的手段就是同步.同步可分为阻塞型同步(Blocking ...

  9. 无锁编程与有锁编程的效率总结、无锁队列的实现(c语言)

    1.无锁编程与有锁编程的效率 无锁编程,即通过CAS原子操作去控制线程的同步.如果你还不知道什么使CAS原子操作,建议先去查看相关资料,这一方面的资料网络上有很多. CAS实现的是硬件级的互斥,在线程 ...

  10. 【算法】CAS的实现和无锁编程

    CAS(Compare and swap,比较与交换) 是一种有名的无锁算法.比较与交换,先比较,发现与预期一致,说明没有其他线程改动过,于是再交换.如果与预期不一致说明改动过,就再来一次. 与各类锁 ...

最新文章

  1. 科技公司重新关注2级以上驾驶员辅助
  2. java只有整形才能运算符为,java语言基础(二)
  3. Python正则表达式:match(),search(),findall()与finditer()的用法
  4. 使用Hash直接登录Windows
  5. 自定义控件:视差特效
  6. 用固定收敛标准网络的迭代次数比较两张图片的相似度
  7. Caffe代码导读(2):LMDB简介
  8. 【C++ Primer】自己动手编写函数 atoi(char *str)
  9. maven 构建web程序出现问题
  10. Web安全——易班优课YOOC课群在线测试自动答题解决方案
  11. 【转】Lucene 工作原理
  12. 封装之--通过类中公有方法访问私有成员变量
  13. Java:将JDBC ResultSet作为JSON流式传输
  14. 使用DataTable动态绑定GridView
  15. 【读书笔记——开关电源】《精通开关电源设计》(1)
  16. Oracle数据库的ORA-00257故障解决过程(转载)
  17. Python打造一款属于自己的翻译词典
  18. Java泛型对象的实例化
  19. 基金定投--1.基金的基础知识
  20. python游戏编程

热门文章

  1. spring动态代理的实现方式
  2. 985高校硕导跳槽高中当老师,博士扎堆中小学,是内卷还是进步?
  3. Centos7远程桌面win7
  4. 一些常用单位之间的换算
  5. 妈妈!我也会做植物大战僵尸啦!
  6. STC89C52RC的AD7705读写实验(软件SPI)
  7. 防火墙 firewall 及端口查看
  8. 新冠最新研究进展(2021年11月)
  9. 局域网弱口令扫描工具_“菜鸟黑客”必用兵器之“扫描篇”
  10. DevExpress GridView 排序状态下新增行不参与排序