网站首页 > 资源文章 正文
CAS(Compare and swap)直译过来就是比较和替换,是一种通过硬件实现并发安全的常用技术,底层通过利用CPU的CAS指令对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作。仔细观察J.U.C包中类的实现代码,会发现这些类中大量使用到了CAS,所以CAS是Java并发包的实现基础。它的实现过程是,有3个操作数,内存值V,旧的预期值E,要修改的新值U,当且仅当预期值E和内存值V相同时,才将内存值V修改为U,否则什么都不做。
底层实现原理
下面以AtomicInteger为入口来看一下CAS的底层实现原理。AtomicInteger可以用原子方式更新其int类型的属性值value。其中,incrementAndGet方法以原子方式将当前值加1,并返回最新值,具体代码如下。
public final int incrementAndGet() {
for (;;) {
int current = get();
int next = current + 1;
if (compareAndSet(current, next))
return next;
}
}
public final int get() {
return value;
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
上面的代码中有一个旧的期望值expect和将要更新的新值update。实现的关键代码就在compareAndSet方法中,可以看到这里调用了Unsafe类的compareAndSwapInt方法,进入这个方法发现使用了native修饰,也就是这里将会通过JNI调用非Java实现的代码。
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
继续深入代码进行分析,就需要进入OpenJDK的源码查看c++的代码,代码跟踪顺序是:unsafe.cpp、atomic.cpp,接下来会根据操作系统和处理器的不同来选择对应的调用代码,这里以Windows和x86处理器为例进入atomic_window_x86.inline.hpp,重要代码片段如下:
inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) {
int mp = os::isMP(); // 判断处理器的类型是否是多处理器
_asm {
mov edx, dest
mov ecx, exchange_value
mov eax, compare_value
LOCK_IF_MP(mp)
cmpxchg dword ptr [edx], ecx
}
}
从上面代码可以看到,如果是多处理器,将会为cmpxchg指令添加lock前缀,否则不添加(单处理器自身会维护执行顺序)。对于lock前缀,下面是intel手册的说明:
- 确保对内存读改写操作的原子执行。 在Pentium及之前的处理器中,带有lock前缀的指令在执行期间会锁住总线,使得其它处理器暂时无法通过总线访问内存,很显然,这个开销很大。在新的处理器中,Intel使用缓存锁定来保证指令执行的原子性。缓存锁定将大大降低lock前缀指令的执行开销。
- 禁止该指令,与前面和后面的读写指令重排序。
- 把写缓冲区的所有数据刷新到内存中。
也就是说,如果是多处理器,通过带lock前缀的cmpxchg指令对缓存加锁或总线加锁的方式来实现多处理器之间的原子操作;如果是单处理器,通过cmpxchg指令完成原子操作。
ABA问题
CAS是当且仅当旧的预期值E和内存值V相同时,才将内存值V修改为U,也就是如果内存值V没有发生变化则更新,但是有可能发生内存值原来是A,中间被改成B,后来又被改成A,此时再使用CAS进行检查时发现没有变化,但是实际上发生了变化,这就是ABA问题。
Java并发包下的AtomicStampedReference可以解决ABA问题,内部实现上添加了一个类似于版本号作用的stamp属性,它是被自动更新的。实现上首先检查当前引用是否等于预期引用、当前stamp是否等于预期stamp,如果全部相等,则以原子方式将该引用和该stamp的值设置为给定的更新值。
猜你喜欢
- 2024-10-01 一天花多久时间学习效率最高?(每天花多长时间读书)
- 2024-10-01 Java线程CAS原理深度解析(java中cas的使用场景)
- 2024-10-01 文心一言 VS 讯飞星火 VS chatgpt (342)—— 算法导论23.2 1题
- 2024-10-01 JNI接口的基本规范和操作实践(一)
- 2024-10-01 和前女友复合的那个晚上,我彻底想通了CAS
- 2024-10-01 金九拉儿子MC Gree预计5月出道 将推两首单曲
- 2024-10-01 大厂爱考的 Binder 系统服务注册问题怎么破?
- 2024-10-01 新鲜不绝于耳日韩榜第44期:泰妍夺冠
- 2024-10-01 黑炮世界新大门,感受地下rapper满满的swag
- 2024-10-01 怎样可以加强人的记忆力?(怎样才可以加强记忆力)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)