java atomic CAS

java.util.concurrent.atomic 包中的类使用CAS , 而不是传统意义上的同步

CAS (Compare and Swap) 在处理竞争问题时使用的是乐观锁机制 ( 乐观锁在读的时候不会独占,在写的时候会进行检查 )

CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做

不过上面的步骤实际上会来带ABA问题, 就是线程1 读取了A,然后线程2先将原始值改成了B然后又改回A, 线程1在这之后察觉不到版本变化

要避免ABA问题可以使用AtomicStampedReference

在竞争不激烈的情况下, atomic包下的原子类可以获得更好的性能, 不过即使在竞争激烈的情况下, 新的原子类也可以获得比synchronized更好的性能,只是会消耗更多内存(下面提到的数组)

当多个线程同时更新某个原子类实例时, 这个类可以独立的保存每个线程所做的更新

操作值会被保存在一个数组里,  每个线程都可以快速返回, 当某个线程是图获取当前值时, 操作值会被累加起来

package testgc;

import java.util.concurrent.atomic.AtomicInteger;

public class TestVolatitle {
     
    public static AtomicInteger count = new AtomicInteger(0);
 
    public static void inc() {
 
        //这里延迟1毫秒,使得结果明显
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }
 
        count.getAndAdd(1);
        
        //我修改后的输出位置
        System.out.println("运行结果:Counter.count=" + TestVolatitle.count);
    }
 
    public static void main(String[] args) throws InterruptedException {
 
        //同时启动10个线程,去进行i++计算,看看实际结果
 
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                public void run() {
                    TestVolatitle.inc();
                }
            }).start();
        }
        
        Thread.sleep(3000);

        //原程序的输出位置在这里
        System.out.println("主线程输出:Counter.count=" + TestVolatitle.count);
    }
}
运行结果:Counter.count=5
运行结果:Counter.count=5
运行结果:Counter.count=5
运行结果:Counter.count=6
运行结果:Counter.count=8
运行结果:Counter.count=5
运行结果:Counter.count=10
运行结果:Counter.count=5
运行结果:Counter.count=9
运行结果:Counter.count=7
主线程输出:Counter.count=10
运行结果:Counter.count=1
运行结果:Counter.count=7
运行结果:Counter.count=6
运行结果:Counter.count=5
运行结果:Counter.count=8
运行结果:Counter.count=4
运行结果:Counter.count=3
运行结果:Counter.count=2
运行结果:Counter.count=9
运行结果:Counter.count=10
主线程输出:Counter.count=10