CAS

CAS(Compare-And-Swap)

CAS(Compare-And-Swap,比较并交换)是一种重要的并发编程中的原子操作,用于实现多线程环境下的同步控制。

基本概念

CAS操作包含三个操作数:

  1. 内存位置(V)
  2. 预期原值(A)
  3. 新值(B)

操作逻辑:当且仅当内存位置V的值等于预期原值A时,处理器才会将该位置的值更新为新值B,否则不执行任何操作

工作原理

bool CAS(V, A, B) {
    if (V == A) {
        V = B;
        return true;
    }
    return false;
}

原子性

整个操作(比较和交换)视为一条指令,不会被别的线程打断,通过 Unsafe 类的 compareAndSwapXxx 来实现的

优缺点

优点
synchronized 是悲观锁,每次获取资源都要先获得锁,不管有没有线程竞争
虽然 JDK6 以后有锁升级,但是重量级锁已经深入人心了,先这样举例吧,或者想想 ReentrantLock
CAS 没有获取锁的动作,直接尝试修改,也不会有线程上下文切换、唤醒等开销

缺点
ABA问题(可通过添加版本号解决)
自旋时间长时CPU开销大(所以锁升级过程中不是一直自旋,一定次数后还是会升级为重量级锁)
只能保证一个共享变量的原子操作

AtomicInteger

public class AtomicInteger extends Number implements java.io.Serializable {
  
  	// 值
  	private volatile int value;
  
  	// Unsafe 类
  	private static final Unsafe U = Unsafe.getUnsafe();
  
    // 获取 value 的内存偏移量
  	private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value");
  
		// 先返回当前值,再 +1(i++)
		public final int getAndIncrement() {
        return U.getAndAddInt(this, VALUE, 1);
    }

		// 先 +1,再返回新值(++i)
    public final int incrementAndGet() {
        return U.getAndAddInt(this, VALUE, 1) + 1;
    }

		// 先返回当前值,再增加 delta
    public final int getAndAdd(int delta) {
        return U.getAndAddInt(this, VALUE, delta);
    }

		// 先增加 delta,再返回新值(i += delta)
		public final int addAndGet(int delta) {
        return U.getAndAddInt(this, VALUE, delta) + delta;
    }

		// 先 -1,再返回新值(--i)
		public final int decrementAndGet() {
        return U.getAndAddInt(this, VALUE, -1) - 1;
    }

		// 手动 CAS 操作,若当前值等于 expect 则更新为 update
		public final boolean compareAndSet(int expectedValue, int newValue) {
        return U.compareAndSetInt(this, VALUE, expectedValue, newValue);
    }
  
}
posted @ 2023-02-10 18:30  CyrusHuang  阅读(44)  评论(0)    收藏  举报