在java中,使用锁线程会被阻塞,而且阻塞的时候线程切换上下文会有很大的开销。而volatile也只能解决共享变量中可见性的问题。不能解决原子问题。
CAS通过硬件保证了原子性,而且是非阻塞的。
下面以一个方法简单介绍
public final native boolean compareAndSwapInt(Object o, long offset,
int expected,
int x);
o对象内存的位置,offset是对象中的偏移量,expected是变量预期的值,x为要更新的值。
如果内存中的值和expected的值是相同的,那就把值更新为x。
该方法为native方法,实现也是用c++实现的。
那么这个操作就很安全吗?
我们认为当前的这个值和内存实际的值是相同的就可以更新。看起来没问题对吧。
那来说下CAS操作中的ABA问题。
开了两个线程,a,b(注意! ab 是不小心 才开启两个线程)
当前值x=100
a线程 减50块
b线程 减50块
a线程执行完后 x=50
这时 c线程 加50 x=100
b还在阻塞
b执行完后 x=50
a 和b 应该只执行一次。但却执行了两次 导致出现问题。
如果变量的值能只朝着一个方向,如增大,那就不会出现这样的问题了。