【多线程】CAS的应用 | CAS的概念 | 实现原子类 | 实现自旋锁

文章目录

    • 一、CAS
          • 1.什么是CAS
          • 2.实现原子类
          • 3.实现自旋锁


一、CAS

1.什么是CAS

Compare and swap 比较并交换。

比较交换的是 内存 和 寄存器

比如此时有一个内存 : M。 还有两个寄存器A,B

​ CAS ( M , A , B ) :如果M和A的值相同的话,就把M和B的值进行交换(交换的目的是为了把B赋值给M,M = B),同时整个操作返回 true。如果M和A的值不同的话,无事发生,同时整个操作返回false。

//伪代码:
boolean CAS(address, expectValue, swapValue) {if (&address == expectedValue) {&address = swapValue;return true;}return false;
}
  • CAS其实是一个CPU指令,一个CPU指令,就可以完成上述比较交换的逻辑。
  • 单个的CPU指令是原子的。所以可以使用CAS来完成一些操作来代替“加锁”。为编写线程安全的代码提供了线的思路,基于CAS实现线程安全的方式,也叫“无锁编程”。

优点:保证线程安全,同时避免发生阻塞。

缺点:代码可读性差,并且只能适用在特定场景,不如加锁普适。

​ CAS本质上是CPU提供的指令,被操作系统封装后,提供成为APi。又再次被JVM进行封装,提供成API,最终由程序员调用方法实现操作。

2.实现原子类

之前int count++的操作,就不是原子的(load,add,save)

在Java标准库中,提供了原子类,例如AtomicInteger,基于CAS的方式对int进行封装,++就封装成原子操作了。

    public static AtomicInteger count = new AtomicInteger(0);//对int进行原子化包装//0作为构造方法的参数public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(()->{for (int i = 0; i < 50000; i++) {count.getAndIncrement();//count++; 后置++
//                count.incrementAndGet();//++count  前置++
//                count.getAndDecrement();//count--; 后置--;
//                count.decrementAndGet();//--count 前置--}});Thread t2 = new Thread(()->{for (int i = 0; i < 50000; i++) {count.getAndIncrement();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}

在Java中,有些操作是偏底层的操作,在使用时有着更多的注意事项,稍有不慎就容易写出问题。这些操作就同一放在unsafe这个类中

在这里插入图片描述

//伪代码
class AtomicInteger {private int value;//相当于内存public int getAndIncrement() {int oldValue = value;//oldValue相当于寄存器    while ( CAS(value, oldValue, oldValue+1) != true) {//CAS(内存,寄存器A,寄存器B)oldValue = value;}return oldValue;}
}

寄存器A先保存当前内存的值,CAS来判断此时有没有被穿插执行。如果没有穿插执行,内存的值等于寄存器A的值,把寄存器B(B执行+1操作)的值赋值给内存,同时CAS返回的是true,循环不成立,返回是是自增前的值。

如果被穿插执行了,CAS中,内存的值不等于寄存器A的值,CAS直接返回false.此时循环成立,将被穿插执行过的内存值,重新赋值给寄存器A,也就是说要再读一遍内存。再次执行CAS。

线程不安全的本质是进行操作的过程中,穿插执行。

1.加锁是通过阻塞的方式,避免穿插。

2.CAS是通过重试的方式,避免穿插。如果值和之前不相等了,重新更新一下,在进行操作。

3.实现自旋锁
//伪代码:
public class SpinLock {private Thread owner = null;//记录当前这个锁被哪个线程获取到。 null表示未加锁public void lock(){//加锁// 通过 CAS 看当前锁是否被某个线程持有. // 如果这个锁已经被别的线程持有, 那么就自旋等待. // 如果这个锁没有被别的线程持有, 那么就把 owner 设为当前尝试加锁的线程. while(!CAS(this.owner, null, Thread.currentThread())){}}public void unlock (){//解锁this.owner = null;}
}
  • while循环中,CAS判断当前owner是不是未加锁状态。如果是未加锁的,就把owner赋值成 Thread.currentThread())(调用lock方法的线程引用)进行加锁。如果已经被加锁了,CAS返回false,取反之后,while就会反复执行。一旦其他线程释放了这个锁,owner变成null时,因为while不停循环,就会立即拿到当前这把锁。

缺点:while循环在忙等的过程中,不断消耗CPU资源。如果加锁的概率不大,付出的CPU资源就是值得的。如果当前的锁冲突很激烈,可能会拿不到,此时自旋锁就不适用了。

点击移步博客主页,欢迎光临~

偷cyk的图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/826669.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

排序之插入排序:从斗地主到插入排序

目录 1.斗地主如何摸牌 2.从摸牌想到插入排序 3.完成插入排序 4.结束语 1.斗地主如何摸牌 不知道各位是否玩过几乎人人都玩过的斗地主游戏呢&#xff1f;相必各位或多或少都玩过一点&#xff0c;再没玩过也看别人打过。今天博主就将从这个游戏为大家讲解我们的插入排序。 在…

C语言经典例题-17

1.最小公倍数 正整数A和正整数B的最小公倍数是指能被A和B整除的最小的正整数&#xff0c;设计一个算法&#xff0c;求输入A和B的最小公倍数。 输入描述&#xff1a;输入两个正整数A和B。 输出描述&#xff1a;输出A和B的最小公倍数。 输入&#xff1a;5 7 输出&#xff1a…

Linux内核驱动开发-001字符设备开发-001Led驱动

上节完成了内核驱动框架的搭建&#xff0c;下面将利用Linux内核驱动第一个字符设备文件&#xff0c;即Led驱动。1驱动程序编写 /*************************************************************************> File Name: led.c> Author: yas> Mail: rage_yashotmail…

React vs Vue.js:两种流行框架背后的设计哲学差异

Vue.js 和 React 虽然都是流行的前端框架,但在设计哲学上有一些显著差异。这些差异源自它们不同的设计目标和出发点。 vue.js Vue.js 的核心设计原则是"渐进式"。它旨在尽可能降低学习成本和入门门槛,并与其他库和项目保持良好的整合性。Vue 的设计注重简单性和直观…

C语言堆区内存管理

一、C语言编译的内存分配 二、堆区空间的分配 1、malloc函数 功能&#xff1a;从堆区分配内存 #include <stdlib.h> void *malloc(unsigned int size)//size 分配内存的字节数2、free函数 功能&#xff1a;释放内存 #include <stdlib.h> void free(void *ptr)…

数据恢复宝典:应对磁盘损坏无法读取的终极攻略

当电脑屏幕上突然弹出“磁盘损坏无法读取”的提示时&#xff0c;许多人的心情都会瞬间跌入谷底。那些存储在磁盘中的重要文件、珍贵的回忆&#xff0c;似乎在一瞬间都化为乌有。面对这样的困境&#xff0c;我们该如何应对&#xff1f;本文将深入探讨磁盘损坏无法读取的原因&…

常见的经典目标检测算法

目标检测是计算机视觉领域的一个核心任务&#xff0c;它涉及到识别图像中的物体并确定它们的位置。以下是一些常见的经典目标检测算法&#xff1a; R-CNN系列 R-CNN&#xff08;Region-based Convolutional Neural Network&#xff09;是一种用于目标检测的算法&#xff0c;它…

深度学习500问——Chapter08:目标检测(2)

文章目录 8.2.4 R-FCN 8.2.5 FPN 8.2.6 Mask R-CNN 8.2.4 R-FCN R-FCN 有哪些创新点 R-FCN仍然属于two-stage目标检测算法&#xff1a;RPN R-FCN Fully convolutional位置敏感得分图&#xff08;position-sentive score maps&#xff09; our region-based detector is ful…

开源数据库postgresql在统信系统上的离线安装shell脚本

一个tar包&#xff1a;pgsql_install.tar.bz2 #!/bin/sh echo "安装pgsql_15.4" rm -rf /home/postgres/postgresql mysqldir"/home/postgres" mkdir -p $mysqldir cp /home/pgsql_install.tar.bz2 $mysqldir cd $mysqldirtar -jxvf pgsql_install.tar.bz…

OpenVINO安装教程 npm版

从 npm Registry安装 OpenVINO™ 工具套件的英特尔发行版 请注意&#xff1a; 仅提供 JavaScript API 专用于所有主要操作系统的用户&#xff1a;Windows、Linux 和 macOS &#xff08;所有 x86_64 / ARM64 架构&#xff09; macOS 仅支持 CPU 推理 系统要求软件要求 Window…

Python 数据结构和算法实用指南(二)

原文&#xff1a;zh.annas-archive.org/md5/66ae3d5970b9b38c5ad770b42fec806d 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;列表和指针结构 我们已经在 Python 中讨论了列表&#xff0c;它们方便而强大。通常情况下&#xff0c;我们使用 Python…

【洛谷 P8630】[蓝桥杯 2015 国 B] 密文搜索 题解(字符串+映射+排序)

[蓝桥杯 2015 国 B] 密文搜索 题目描述 福尔摩斯从 X 星收到一份资料&#xff0c;全部是小写字母组成。 他的助手提供了另一份资料&#xff1a;许多长度为 8 8 8 的密码列表。 福尔摩斯发现&#xff0c;这些密码是被打乱后隐藏在先前那份资料中的。 请你编写一个程序&…

【C语言】求最小新整数(贪心算法)

文章目录 题目描述方法一方法二 题目描述 给定一个十进制正整数n(0 < n < 1000000000)&#xff0c;每个数位上数字均不为0。n的位数为m。 现在从m位中删除k位(0<k < m)&#xff0c;求生成的新整数最小为多少&#xff1f; 例如: n 9128456, k 2, 则生成的新整数最…

windows ubuntu 子系统:肿瘤全外篇,2. fq 数据质控,比对。

目录 1.质控 2.比对并排序 3.标记PCR重复,使用picard 4.samtools建立索引 首先我们先下载一组全外显子测序数据。nabi sra库&#xff0c;随机找了一个。 来自受试者“16177_CCPM_1300019”(SRR28391647, SRR28398576)的样本“16177_CCPM_1300019_BB5”的基因组DNA配对端文库…

C#字典底层原理

一&#xff1a;前言 Dictionary是一种键值对的形式存放数据&#xff0c;即 key和value一一映射。key的类型没有限制&#xff0c;可以是整数、字符串甚至是实例对象 C#字典源码 时间复杂度 ——Add&#xff1a;O(1) ——Remove&#xff1a;一般情况下为O(1)&#xff0c;最差情…

Android开发如何从入门进阶到架构

最近按照Android学习体系整理了下Android学习课程&#xff0c;这个体系的设计是为了帮助学习者系统性地掌握Android开发的各个方面。。分为入门学习、项目实战、底层原理、性能优化、架构设计、面试和综合能力提升系列。大家按照这个路径来学习一定能够Android架构师。 需要课…

# 从浅入深 学习 SpringCloud 微服务架构(三)注册中心 Eureka(3)

从浅入深 学习 SpringCloud 微服务架构&#xff08;三&#xff09;注册中心 Eureka&#xff08;3&#xff09; 段子手168 1、eureka&#xff1a;高可用的引入 Eureka Server 可以通过运行多个实例并相互注册的方式实现高可用部署&#xff0c; Eureka Server 实例会彼此增量地…

python爬虫小案例——汽车之家

本篇文章是使用bs4中的BeautifulSoup和requests解析网页和获取数据&#x1f451;&#x1f31f; 文章目录 &#x1f31f;前言一、&#x1f349;bs4中的BeautifulSoup二、&#x1f349;bs4的语法三、&#x1f349;内容实践1. 确定想要爬取的内容2. 分析网页3. 获取数据分析 &…

AI预测福彩3D➕体彩排3合并2024年4月21日预测结果

由于今天是周末&#xff0c;周末事情比较多&#xff0c;今天回来比较晚了&#xff0c;数据刚跑完&#xff0c;趁着离开奖还有一段时间&#xff0c;咱们还是把3D和排3的预测合并发布。好了&#xff0c;废话不多说&#xff0c;直接放结果吧&#xff5e; 一.4月21日3D预测结果 …

探索C++的奇妙世界:学习之旅的点点滴滴

在这个信息技术飞速发展的时代&#xff0c;编程语言作为计算机与人类沟通的桥梁&#xff0c;其重要性不言而喻。在众多编程语言中&#xff0c;C以其高效、灵活和强大的特性&#xff0c;吸引了无数编程爱好者的目光。今天&#xff0c;我将与大家分享我学习C的历程和心得&#xf…