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