java中cas,CAS以及它在java中的体现

Compare And Swap:比较和交换

v(内存位置)

a(旧的期望值)

b(改变之后的值)

数据在修改之前,旧的预期值和v中的值一致时,才能修改

java中Atomic相关类就是使用的这种算法实现的。

它和Synchronized相对:

Synchoronized属于悲观锁,认为并发数据操作是一个大概率事件(总有刁民想害朕),我操作的时候,得把数据锁上,别人谁也别想动

而CAS属于乐观锁,它认为并发数据操作是小概率事件,你操作数据之后我再核查一遍,现在的数据和我修改的时候,读取的数据是否一致就没事了,通过比较和交换的方式进行数据修改。

拿 AtomicInteger 的 incrementAndGet 方法举例,这个方法就是给当前对象的数值+1,但是保证了线程安全:

public void test(){

AtomicInteger atomicInteger = new AtomicInteger(1);

atomicInteger.incrementAndGet ();

Integer integer = 1;

integer = integer + 1;

// 以上两种操作,结果是一样的

}

看看CAS再JDK1.8中是怎么实现的:

public final int incrementAndGet() {

// getAndAddInt(this, VALUE, 1) 返回之后进行的 +1 操作

return U.getAndAddInt(this, VALUE, 1) + 1;

}

@HotSpotIntrinsicCandidate

public final int getAndAddInt(Object o, long offset, int delta) {

int v;

// 不停的去判断,现在的值 和 当时修改时读取的值是否一致

do {

// 获取当前变量的值

v = getIntVolatile(o, offset);

// offset:内存地址的值

// v:旧的期望值

// v + delta :进行内存的数据更新

} while (!weakCompareAndSetInt(o, offset, v, v + delta));

// 返回的却是更新前的数值

return v;

}

// 当前内存存放的值 和 旧的期望值 对比的方法

@HotSpotIntrinsicCandidate

public final boolean weakCompareAndSetInt(Object o, long offset,

int expected,

int x) {

return compareAndSetInt(o, offset, expected, x);

}

@HotSpotIntrinsicCandidate

public final native boolean compareAndSetInt(Object o, long offset,

int expected,

int x)

// 从内存中获取此对象的值

@HotSpotIntrinsicCandidate

public native int getIntVolatile(Object o, long offset);

看到最后,殊途同归,最后都看到了native这个关键字,进入c的部分,而comparenAndSetInt 通过查阅资源,底层实现的方式大致是:

判断当前系统是否为多核处理器;

执行 CPU 指令 cmpxchg,如果为多核则在 cmpxchg 加 lock 前缀。

可以清晰的看出,java中的cas是通过底层cpu命令实现对比和交换,通过cpu实现无锁自增。

优点:

1、它属于cpu指令级操作,速度很快

2、没有线程阻塞带来的性能消耗问题

缺点:

1、无法通过它进行并发控制

2、ABA问题:判断的时候,虽然当前值和预期值一致,但是可能是由于其他线程改修数据之后又修改回来,这个时候就不严谨了(这已经不是当初的那个它了)解决此类问题,可以通过添加一个时间戳来解决。

有什么不足欢迎大家指出和交流!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值