使用CAS模拟实现库存并发增加
- 自旋方式实现
java
public static void main(String[] args) throws Exception {
List<Thread> threadList = new ArrayList<>();
AtomicInteger atomicInteger = new AtomicInteger(0);
for (int i = 0; i < 100; i++) {
Thread thread = new Thread(() -> {
boolean success = atomicInteger.compareAndSet(atomicInteger.get(), atomicInteger.get() + 1);
while (!success){
success = atomicInteger.compareAndSet(atomicInteger.get(), atomicInteger.get() + 1);
}
System.out.println(Thread.currentThread().getName() + "更新成功" + atomicInteger.get());
});
thread.start();
threadList.add(thread);
}
for (Thread thread : threadList) {
thread.join();
}
System.out.println(atomicInteger.get());
- API方式实现
java
public static void main(String[] args) throws Exception {
List<Thread> threadList = new ArrayList<>();
AtomicInteger atomicInteger = new AtomicInteger(0);
for (int i = 0; i < 100; i++) {
Thread thread = new Thread(() -> {
atomicInteger.incrementAndGet()
System.out.println(Thread.currentThread().getName() + "更新成功" + atomicInteger.get());
});
thread.start();
threadList.add(thread);
}
for (Thread thread : threadList) {
thread.join();
}
System.out.println(atomicInteger.get());
}
CAS机制总结
CAS机制由CPU提供原子操作保障(以下操作由CPU层面保证原子性,CPU保证了多线程环境下不会对CAS机制造成重复覆盖问题,一旦进入此操作
就必须是一个原子操作了,可以这样理解,【CAS机制是CPU层面提供的最小粒度的同步代码块】)
-
主内存取值
-
比较期望值
-
一致则更新主内存值,不一致则更新失败
多线程CAS机制下更新失败的原因,主要就是比对失败
1. 一个线程工作内存中的数据在比对时,对比预期变量的值已经不一致了,导致此线程更新失败。//非CAS的自旋无法实现,
在更新了主内存中的数据后,其他线程都有可能会重复更新覆盖掉,但CAS机制不会覆盖。CAS机制适合在并发量不大的情况下实现同步机制,如果并发量较大,可能会造成多个线程一直在自旋,占用大量的CPU资源
导致其他任务无法获取cpu时间片,而无法执行任务。
理解其中2个:
-
CAS为CPU提供的原子操作(比较并交换),是CPU层面提供的,多个编程语言都能实现。
-
CAS可以理解为CPU层面能提供的最小的同步代码块,也就是同步机制。 三步 取值 比较 替换(同步操作,这个操作不可能出现多线程覆盖,CPU层面提供的原子操作)。
-
CAS 不适合高并发场景,这可能会导致多个线程大量循环,占用较多CPU资源。