本文介绍CAS、通过案例去演示CAS、CAS的应用场景、如何利用CAS进行原子操作、CAS的缺点。
概述
CAS是一种思想,使用并发场景,是一种原子性的操作,实现不能被其他线程打断的情况。
思路:我认为他应该是A,如果是我就修改,如果不是我就放弃他,可以避免多人修改引发的问题。
具体参数:内存值、预期值、修改值,只有当内存值和预期值相等的时候,才会去修改;利用CPU的指令保证他的原子性。
代码示例
两个线程都去修改公共变量,只有一个可以修改成功,示例代码如下所示。
package com.yang.cas; import javax.management.relation.RoleUnresolved; /** * 模拟CAS操作 */ public class SimulatedCASDemo implements Runnable { private volatile int value; public synchronized int compareAndSwap(int expectedValue, int newValue) { int oldValue = value; if (oldValue == expectedValue) { value = newValue; } return value; } @Override public void run() { compareAndSwap(0, 1); } /** * 两个线程都去修改参数,只有个线程可以修改成功 * 最终的输出结果为1 * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { SimulatedCASDemo simulatedCASDemo=new SimulatedCASDemo(); Thread thread1=new Thread(simulatedCASDemo); Thread thread2=new Thread(simulatedCASDemo); thread1.start(); thread2.start(); thread1.join(); thread2.join(); System.out.println(simulatedCASDemo.value); } }
应用场景
乐观锁
并发容器:concurrentHashMap
原子类
原子类如何实现CAS
原子类AtomicInteger加载unsafe工具,用来直接操作内存数据;用volatile 修饰value字段,保证可见性。
Unsafe可以拿到内存地址,部分代码如下所示:
static { try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private volatile int value; .........................
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2); } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; }
CAS缺点
1.ABA问题:先修改为A,再修改为B,再修改为A,检查和我的值是否相等,乐观锁可以加个版本号
2.自旋时间较长