juc-2-原子变量与CAS算法
i++的原子性问题
例子 int i=10;
i++;
结果 i=10
分析过程
在计算机 底层 会有生成一个临时变量 temp 将i的值赋值给temp
int i=10; ------> int temp =i;
i++; ------> i=i+1;
最后 ------> i=temp;
总结 i++ 过程中 读->改->写的操作
volatile 只能保证读的数据一样 不能保证改->写的操作 的数据一致 所以不能保证线程安全的原子性
原子变量:在 java.util.concurrent.atomic 包下提供了一些原子变量。
原子变量使用volatile修饰
原子变量使用了volatile 和CAS算法
* 1. volatile 保证内存可见性 不能保证原子性 原子性指不可分割
* 2. CAS(Compare-And-Swap) 算法保证数据变量的原子性
* CAS 算法是硬件对于并发操作的支持
* CAS 包含了三个操作数:
* ①内存值 V
* ②预估值 A
* ③更新值 B
* 当且仅当 V == A 时, V = B; 否则,不会执行任何操作。(保证了原子性)
仅仅使用volatile关键字修饰变量
仅仅使用volatile关键字 出现了违背线程安全的原子性
正确的做法 使用原子变量 满足 线程安全的原子性 可见性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 package com.wf.zhang.juc; 2 3 import java.util.concurrent.atomic.AtomicInteger; 4 5 public class TestAtomicDemo { 6 7 8 public static void main(String[] args) { 9 AtomicDemo ad = new AtomicDemo(); 10 11 for (int i = 0; i < 10; i++) { 12 new Thread(ad).start(); 13 } 14 } 15 16 } 17 18 class AtomicDemo implements Runnable{ 19 20 //private volatile int serialNumber = 0; 21 22 private AtomicInteger serialNumber = new AtomicInteger(0); 23 24 @Override 25 public void run() { 26 27 try { 28 Thread.sleep(200); 29 } catch (InterruptedException e) { 30 } 31 32 System.out.println(getSerialNumber()); 33 } 34 35 public int getSerialNumber(){ 36 37 //return serialNumber++; 38 39 return serialNumber.getAndIncrement(); //得到值并且自增 40 } 41 42 43 }
古人学问无遗力,少壮工夫老始成。
纸上得来终觉浅,绝知此事要躬行。