JUC--volatiley&CAS

public class VolatileTest {
    public static void main(String[] args) {
        ThreadDemo td = new ThreadDemo();
        new Thread(td).start();
        while(true){
            if(td.getFlag()){
                System.out.println("========");
                break;
            }
        }

    }
}
class ThreadDemo implements Runnable{
   private boolean flag=false;

    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag=true;
        System.out.println("flag="+getFlag());

    }
    public boolean getFlag(){
        return flag;
    }
}

flag是main thread和td共享的數據,他們都在各自的線程內有一個copy,因爲while true的速度十分快,main thread不能讀取到td修改後的值,因此只能輸出 flag=true。java

內存不可見性:當多個thread操做共享數據時,彼此不可見算法

volatile:當多個thread操做共享數據時,保證數據是可見的,內存柵欄   能夠理解爲多個線程直接操做主存中的數據安全

由於使用vloatile 不能指令重排  因此效率低併發

volatile相比synchronized:dom

  是一種較爲輕量級的同步策略,volatile不具有互斥性,兩個線程能夠同時訪問共享數據,volatile不能保證變量的原子性,ide

 

 

原子性問題:i++this

  

如下狀況使用volatile不能解決非原子性問題:內存可見性問題依然存在atom

public class AtomicTest {
    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 int serialNum=0;
    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+":"+getSerialNum());
    }
    public int getSerialNum(){
        return serialNum++;
    }
}

2、使用源自變量 java.util.concurrent.atomic 原子變量包spa

  1.使用volatile保證內存可見性線程

  2.使用CAS compare and swap算法保證數據的原子性

    CAS是硬件對於併發操做共享數據的支持  

    CAS包含三個操做數:

      內存值V 預估值A 更新值B

(1)首先讀取內存之V 在替換的時候讀取舊值A 

 

AtomicInteger:保證線程安全  內存可見性 原子性問題

private AtomicInteger serialNum=new AtomicInteger();
    @Override
    public void run() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+":"+getSerialNum());
    }
    public int getSerialNum(){
        return serialNum.getAndIncrement();
    }

 

 CAS算法的模擬:

public class TestCAS {
    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 expectVal = cas.get();
                    boolean b= cas.compareAndSwap(expectVal,(int)(Math.random()*101));
                }
            }).start();
        }
    }
}

class CompareAndSwap {
    private int value;
    public synchronized int get() {
        return value;
    }
    public synchronized int cas(int expectVal, int newVal) {
        int oldVal = value;
        if (oldVal == expectVal)
            this.value = newVal;
        return oldVal;
    }
    public synchronized boolean compareAndSwap(int expectVal, int newVal) {
        return  expectVal==cas(expectVal,newVal);
    }
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息