Java多线程中的CAS
创始人
2024-05-29 10:06:51
0

多线程中的CAS


什么是CAS

CAS CompareAndSwap,或者 CompareAndSet,
是一个能够比较和替换的方法。
这个方法能够在多线程环境下保证对一个共享变量进行修改时的原子性不变。
通常,CAS方法会传递三个参数,
● 第一个参数V表示要更新的变量;
● 第二个参数E表示期望值;
● 第三个参数U表示更新后的值。

更新的方式是:
如果V==E ,表示预期值和实际值相等,则将 V修改成U 并返回 true,
否则修改失败返回false。

Created with Raphaël 2.3.0开始V==E?更新变量V并设置值为U返回true不更新变量V返回falseyesno

CAS是如何实现的

在Java中的Unsafe类中提供了CAS方法,针对int类型变量的CAS方法定义如下:

public finlal native boolean compareAndSwapInt(Object o,long offset,int expect,int update);
它的四个参数:
● o,表示当前的实例对象
● offset,表示实例变量的内存地址偏移量
● expect,表示预期值
● update,表示要更新的值

compareAndSwapInt()是一个native方法,该方法是在JVM中定义和实现的。
基于compareAndSwapInt()方法,在JVM源码中的unsafe.cpp文件中,找到该方法:

UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))UnsafeWrapper("Unsafe_CompareAndSwapInt");//将Java对象转化为JVM中的对象oop p = JNIHandles::resolve(obj);//根据offset计算value的地址jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);//比较addr和e是否相等,如果相等就把x赋值到目标字段,该方法返回修改之前的目标字段的值。return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
UNSAFE_END

Atomic:compxchg() 方法的定义在atomic.cpp文件中:

unsigned Atomic::cmpxchg(unsigned int exchange_value,volatile unsigned int* dest, unsigned int compare_value) {assert(sizeof(unsigned int) == sizeof(jint), "more work to do");return (unsigned int)Atomic::cmpxchg((jint)exchange_value, (volatile jint*)dest,(jint)compare_value);
}

对于CAS操作,不同的操作系统和CPU架构,保证原子性的方法可能会不一样,而JVM是跨平台的语言,它需要在任何平台和CPU架构下都保持一致。Atomic:cmpxchg() 会在预编译阶段确定调用哪个平台下的重载。
在这里插入图片描述
以Linux为例,进入 atomic_linux_x86.inline.hpp中:

inline jint     Atomic::cmpxchg    (jint     exchange_value, volatile jint*     dest, jint     compare_value) {//判断是否多核CPUint mp = os::is_MP();//asm表示内嵌汇编代码//volatile通知编译器对访问该变量的代码不再进行优化//LOCK_IF_MP(%4)表示如果CPU是多核的,则需要为compxchgl指令增加一条Lock指令__asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)": "=a" (exchange_value): "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp): "cc", "memory");return exchange_value;
}

上述代码的功能是基于汇编指令cmpxchgl 从主内存执行比较及替换的操作来实现数据的变更。在多核心CUP的情况下,为了保证多核心CPU下执行该命令的原子性,会增加一个Lock指令。CAS的底层用到了锁的机制。

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...