cas原理

1什么是cas
是一种用来实现并发的一种安全策略
思路如下
我认为V的值应该是A,如果是的话那我就把它改成B,如果不是A(说明被别人修改过了),那我就不修改了,避免多人同时修改导致出错
CAS有三个操作数∶内存值V、预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,才将内存值修改为B,否则什么都不做。最后返回现在的V值
最终安全性的保证是由指令集中有 cmpxchg 指令完成 CAS 功能。
sun.misc.Unsafe 中 CAS 的核心方法:

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);

这三个方法可以对应去查看 openjdk 的 hotspot 源码:
源码位置:hotspot/src/share/vm/prims/unsafe.cpp

#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)}, {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)}, {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z",      FN_PTR(Unsafe_CompareAndSwapLong)}, 

上述三个方法,最终在 hotspot 源码实现中都会调用统一的 cmpxchg 函数,可以在 hotspot 源码中找到核心代码。
源码地址:hotspot/src/share/vm/runtime/Atomic.cpp
cmpxchg 函数源码:

jbyte Atomic::cmpxchg(jbyte exchange_value, volatile jbyte*dest, jbyte compare_value) { 		 assert (sizeof(jbyte) == 1,"assumption."); 	
	 uintptr_t dest_addr = (uintptr_t) dest;                                                                                      uintptr_t offset = dest_addr % sizeof(jint); 	
	   volatile jint*dest_int = ( volatile jint*)(dest_addr - offset); 		
// 对象当前值 		 jint cur = *dest_int; 	
// 当前值cur的地址 		 jbyte * cur_as_bytes = (jbyte *) ( & cur); 		
 // new_val地址 		 jint new_val = cur; 	
   jbyte * new_val_as_bytes = (jbyte *) ( & new_val); 		 
    // new_val存exchange_value,后面修改则直接从new_val中取值 		 new_val_as_bytes[offset] = exchange_value; 		
    // 比较当前值与期望值,如果相同则更新,不同则直接返回 		
  while (cur_as_bytes[offset] == compare_value) { 		 
  // 调用汇编指令cmpxchg执行CAS操作,期望值为cur,更新值为new_val 	
  		 jint res = cmpxchg(new_val, dest_int, cur); 			
       if (res == cur) break; 			
     cur = res; 			 
     new_val = cur; 			
    new_val_as_bytes[offset] = exchange_value; 	
         } 		
     // 返回当前值 	
   return cur_as_bytes[offset]; } 

源码中具体变量添加了注释,因为都是 C++ 代码,所以作为了解即可 ~
jint res = cmpxchg(new_val, dest_int, cur);
这里就是调用了汇编指令 cmpxchg 了,其中也是包含了三个参数,跟CAS上的参数能对应上。
3 应用场景
cas是一种乐观锁的实现,适用并发不是很高的场景
4优缺点
aba 问题 ,自旋的消耗
时间戳可以解决aba问题,自旋的消耗 由于通过自旋的操作,所以长时间自旋会占用过多cpu

Java CAS(Compare And Swap,比较并交换)是一种常用于多线程编程的原子操作。其主要作用是在多线程环境下保证变量的原子性和一致性,解决多线程竞争条件下的并发问题。 Java CAS原理是通过比较内存中的值与期望值是否相等来确定是否进行交换,其核心思想是利用硬件的原子性操作来实现并发的同步,而不需要使用锁(synchronized)等机制。 具体来说,CAS操作包含三个参数:内存地址、旧的预期值和新的值。 1. 首先,CAS会将当前内存地址中的值与旧的预期值进行比较,如果相等,则说明内存中的值未被其他线程修改。 2. 然后,CAS会使用新的值来更新内存地址中的值,完成交换操作。 3. 最后,CAS会返回旧的预期值,可以通过返回值进行判断操作是否成功。 需要注意的是,CAS是一种乐观的并发控制方式,它不会阻塞线程,而是通过不断重试的方式来保证操作的原子性。如果CAS操作失败,那么线程会重新读取内存中的值,并重新尝试进行CAS操作,直到成功为止。 然而,CAS也存在一些问题。首先,CAS需要频繁地读取和写入内存,这对内存带宽的要求较高;其次,由于CAS操作是无锁的,因此存在ABA问题,即在操作过程中,如果其他线程修改了预期值两次并恢复为原来的值,CAS操作无法察觉。 总之,Java CAS作为一种基于硬件支持的原子操作,可以在多线程环境下实现高效的同步控制,然而它也需要开发人员自行处理ABA问题以及确保程序的正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晴天M雨天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值