CAS解析
创始人
2024-04-04 09:23:12
0

CAS

概念

CAS是支持并发的第一个处理器提供原子的测试并设置操作,通常在单位上运行这项操作。操作数为V,A,B。
处理器(包括 Intel 和 Sparc 处理器)使用的最通用的方法是实现名为 比较并转换或 CAS 的原语。(在 Intel 处理器中,比较并交换通过指令的 cmpxchg 系列实现。PowerPC 处理器有一对名为“加载并保留”和“条件存储”的指令,它们实现相同的目地;MIPS 与 PowerPC 处理器相似,除了第一个指令称为“加载链接”。)
CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置的值即可。
通常将 CAS 用于同步的方式是从地址 V 读取值 A,执行多步计算来获得新值 B,然后使用 CAS 将 V 的值从 A 改为 B。如果 V 处的值尚未同时更改,则 CAS 操作成功。
类似于 CAS 的指令允许算法执行读-修改-写操作,而无需害怕其他线程同时修改变量,因为如果其他线程修改变量,那么 CAS 会检测它(并失败),算法可以对该操作重新计算。清单 3 说明了 CAS 操作的行为(而不是性能特征),但是 CAS 的价值是它可以在硬件中实现,并且是极轻量级的(在大多数处理器中)。

基本原理

在这里插入图片描述
采用了乐观锁思想,首先线程获取到共享资源变量的值,然后再计算出要赋予共享变量的新值,最后,调用硬件处理器的CAS机制,保证原子操作:首先比较内存中共享变量现在的值是否与线程中存入的共享变量的旧值相等,如果相等,则将新值赋予共享变量,赋值成功,这个过程是原子性的,由底层处理器完成,在这期间共享变量值不会被其他线程所修改。
如果比较内存中值与线程存的旧值不相等,说明已经被其他线程所修改过了,此时修改失败,需要采用自旋机制,重新获取到最新的共享变量的值,然后重新走一遍CAS流程。

Unsafe类

jdk的CAS机制有Unsafe类调用底层操作系统所实现,相关方法如下:

public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

Unsafe类还有很多操作底层的功能,如操作系统的内存分配等等。但是Unsafe构造方法是私有的,所以只能通过反射获取。有关Unsafe类的其他作用和详解,可参考文章:java中的Unsafe

CAS存在问题

ABA问题
如果一个变量初次读取的时候是A值,并且在准备赋值的时候检查到它仍然是A值,那我们就能说明它的值没有被其它线程修改过了吗?如果这段期间它的值曾经被改成了B,然后又改回A,那么CAS操作就会误认为它从来没有被修改过。这个漏洞称为CAS操作的ABA问题。java.util.concurrent包为了解决这个问题,提供了一个带有标记性的原子引用类AtomicStampedRenference,它可以通过控制变量值的版本来保证CAS的正确性。不过目前来说这个类比较鸡肋,大部分情况下ABA问题并不会影响程序并发的正确性,如果需要解决ABA问题,使用传统的互斥同步可能回避原子类更加高效。

有限性
一次CAS指令只能控制一个变量,不能控制多个变量,如果想保证多个变量的安全性,则需要多个CAS指令,或者将多个变量组成一个对象,将对象进行CAS操作。

效率问题
效率问题:前面提到,如果存在多个线程竞争,可能导致CAS失败,此时可能需要循环(自旋)执行CAS,竞争激烈情况下会对性能有一定影响;

Atomic相关类解析

Atomic类采用CAS机制,保证并发安全,下面以AtomicInteger为例,分析使用和原理:

//原子设置为给定值并返回旧值。
public final int getAndSet(int newValue) {return unsafe.getAndSetInt(this, valueOffset, newValue);}
//如果当前值==预期值,则原子地将该值设置为给定的更新值。
public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
//当前值原子递增一public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}
//原子地将当前值减少一public final int getAndDecrement() {return unsafe.getAndAddInt(this, valueOffset, -1);}

等等一系列原子操作,都是利用了CAS原理。保证在多线程环境下,对一个变量的操作保证安全性。
其他相关原子操作类:
在这里插入图片描述

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...