为了实现线程安全问题,我们常用的方式便是使用锁,例如synchronized、Lock,但是锁是一种比较重的资源,使用锁比较损耗性能,那么我们是否可以使用其他方案实现线程安全呢,答案就是cas
cas的意思就是比较并交换的意思,通过比较并替换,便可以实现对共享变量的线程安全操作。我们来看一下下面这个例子
public class AtomicIntegerDemo {
private static AtomicInteger atomicInteger = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for(int i = 0; i < 1000; i++) {
executorService.execute(()-> atomicInteger.getAndAdd(1));
}
Thread.sleep(1000);
System.out.println(atomicInteger.get());
}
}AtomicInteger 便是采用的cas,我们来看一下他内部的实现,
public final int getAndAdd(int delta) {
return unsafe.getAndAddInt(this, valueOffset, delta);
}
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是否存在问题呢?
ABA问题
第一个线程读取到的最小值问A,第二个线程将A线程了 B ,此时,另外一个线程将B改成了A,这个时候,线程A再进行数据对比交换的时候,便会人为共享变量没有变化,数据交换成功,但是,实际上数据已经发生了变化
为了解决ABA为了,我们需要在数据每次发生变化时,都产生一个唯一变量,因此,我们可以采用版本号的方式,来时解决ABA问题。
| 留言与评论(共有 0 条评论) “” |