原子变量-CAS算法
1. i++的原子性问题
i++的计算原理:读 - 改 - 写
int temp = i;
i = i + 1;
将i++赋给其他变量的时候会将temp的值赋给其他变量,比如:
int i = 10;
i = i++; // 这里i的值就是10,i++的值实际上就是临时变量temp的值
i++的原子性问题实例
package com.atguigu.juc;
public class TestAtomicDemo {
public static void main(String[] args) {
AtomicDemo atomicDemo = new AtomicDemo();
for(int j = 0; j< 20 ;j++){
new Thread(atomicDemo).start();
}
}
}
class AtomicDemo implements Runnable{
private int i = 0;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println(i++);
}
}
分析过程如下
2. 原子变量
jdk1.5后java.util.concurrent.atomic包下提供了常用的原子变量
工作原理:
-
volatile保证内存可见性
-
CAS (Compare-And-Swap)算法保证数据的原子性
CAS算法是
硬件
对于并发操作共享数据的支持CAS包含了三个操作数:
内存值 V
预估值(旧值) A更新值(新值) B
当且仅当V == A时, 才将B的值更新到共享变量中。否则,将不做任何操作
CAS算法逻辑:读取内存值作为V,计算出新值B后在替换之前再次读取内存值作为预估值A,比较内存值V和预估值A,如果相等则进行替换(比较并替换这个步骤是原子操作)
CAS算法:无锁、非阻塞
1.读取内存值
2.比较并交换
CAS算法与同步锁的比较:
CAS算法效率要高于同步锁,因为替换失败时不会阻塞,会一直重复进行
用原子变量改写3.1中的示例,解决i++的原子性问题
package com.atguigu.juc;
import java.util.concurrent.atomic.AtomicInteger;
public class TestAtomicDemo {
public static void main(String[] args) {
AtomicDemo atomicDemo = new AtomicDemo();
for(int j = 0; j< 20 ;j++){
new Thread(atomicDemo).start();
}
}
}
class AtomicDemo implements Runnable{
// private volatile int i = 0;
private AtomicInteger i = new AtomicInteger(0);
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println(i.getAndIncrement());
}
}
标签:JUC,变量,++,原子,CAS,AtomicDemo,public
From: https://www.cnblogs.com/wzzzj/p/18045236