三、原子变量与CAS算法

原子变量:jdk1.5 后 java.util.concurrent.atomic 包下提供了常用的原子变量:

- AtomicBoolean
- AtomicInteger 
- AtomicLong
- AtomicReference 
- AtomicIntegerArray
- AtomicLongArray 
- AtomicMarkableReference 
- AtomicReferenceArray 
- AtomicStampedReference

1.以上类中的变量都是volatile类型:保证内存可见性
2.CAS算法:保证数据的原子性

CAS (Compare-And-Swap) 算法:是操作系统硬件对并发操作共享数据的支持,用于管理对共享数据的并发访问。
CAS 是一种无锁的非阻塞算法的实现。
CAS包含三个操作数

内存值 V 
预估值 A 
更新值 B

当且仅当,V==A 时,才将 B 的只值赋给 A,否则,将不做任何操作。  //(CAS算法的一个特性)

代码示例:

public class TestAtomicDemo {

    public static void main(String[] args) {
        AtomicDemo ad = new AtomicDemo();

        for (int i = 0; i < 10; i++) {
            new Thread(ad).start();
        }
    }

}

class AtomicDemo implements Runnable{

//  private volatile int serialNumber = 0;

    private AtomicInteger serialNumber = new AtomicInteger(0);

    @Override
    public void run() {

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }

        System.out.println(getSerialNumber());
    }

    public int getSerialNumber(){
        return serialNumber.getAndIncrement();//实现i++操作
    }
}

[注] i++ 的实现原理

i++ 的原子性问题:i++ 的实际上分为三个步骤:"读 - 改 - 写"
即,i++的底层实际上是:
	int temp=i; //temp 是个临时变量
	i=i+1;
	i=temp;

模拟CAS算法 :

CAS的流程:获取 —> 比较 —> 设置

public class TestCompareAndSwap {
    public static void main(String[] args) {
        final CompareAndSwap cas=new CompareAndSwap();

        for(int i=0;i<10;i++){
            new Thread(new Runnable(){
                @Override
                public void run() { 
                    int expectedValue=cas.get(); //每次执行前先获取内存中的值
                    boolean isTrue=cas.compareAndSet(expectedValue, (int)(Math.random()*101));
                    System.out.println(isTrue);
                }
            }).start();
        }
    }
}

class CompareAndSwap{
    //内存值
    private int value;

    //获取内存值
    public synchronized int get(){
        return value;
    }

    //比较
    public synchronized boolean compareAndSwap(int expectedValue,int newValue){
        int oldValue=value;//线程读取内存值,与预估值比较
        if(oldValue==expectedValue){
            this.value=newValue;
            return true;
        }
        return false;
    }
  
  	//设置
  	public synchronized boolean compareAndSet(int expectedValue,int newValue){
    	return expectedValue == compareAndSwap(expectedValue,newValue);
  	}
}
posted @ 2019-04-14 01:37  三七二十个一  阅读(516)  评论(0编辑  收藏  举报