java多線程---volatile

來源:互聯網
上載者:User

標籤:共用   線上   工作   不可   可見度   因此   地方   []   關鍵字   

被volatile修飾的變數能夠保證每個線程能夠擷取該變數的最新值,從而避免出現資料髒讀的現象。
當把變數聲明為volatile類型後,編譯器與運行時都會注意到這個變數是共用的,因此不會將該變數上的操作與其他記憶體操作一起重排序。volatile變數不會被緩衝在寄存器或者對其他處理器不可見的地方,因此在讀取volatile類型的變數時總會返回最新寫入的值。在訪問volatile變數時不會執行加鎖操作,因此也就不會使執行線程阻塞,因此volatile變數是一種比sychronized關鍵字更輕量級的同步機制。

  • 1.非volatile變數,讀寫時,每個線程從記憶體copy到cpu緩衝中,多核cpu,每個線程在不同的cpu上被處理。變數會被copy到不同的cpu緩衝中
  • 2.volatile變數,每次從記憶體中讀,跳過了cpu緩衝這一步。
  • 特性
    1.可見度。可見度是指當多個線程訪問同一個變數時,一個線程修改了這個變數的值,其他線程能夠立即看得到修改的值。
    2.有序性。禁止指令重排序最佳化。

eg

public class VolatileTest {        public static volatile int  i = 0 ;        public static class VTTest implements Runnable{            @Override            public void run() {                for (int j = 0; j < 1000; j++) {                    i++;    //可以理解為3步,1:讀到工作記憶體,2:進行+1計算 3:寫入新的i+1                    System.out.println(Thread.currentThread().getId() + ":" + i);                }            }    }        public static void main(String[] args) throws InterruptedException {        Thread[] t = new Thread[10];        for (int i = 0; i < 10; i++) {            t[i] = new Thread(new VTTest());            t[i].start();        }        for (int i = 0; i < 10; i++) {            t[i].join();        }    }}
由於volatile保證了可見度,那麼在每個線程中對i自增完之後,在其他線程中都能看到修改後的值啊,所以有10個線程分別進行了1000次操作,那麼最終i的值應該是1000*10=10000。這裡面就有一個誤區了,volatile關鍵字能保證可見度沒有錯,但是上面的程式錯在沒能保證原子性。可見度只能保證每次讀取的是最新的值,但是volatile沒辦法保證對變數的操作的原子性。比如現在有2個線程,線程1開始讀取i到工作記憶體,進行+1操作,線上程1還沒有進行寫操作,線程2也開始讀取i到工作記憶體,進行+1操作,由於線程1還沒有寫操作,所以線程2的i還是有效,線程1將遞增的結果寫到主記憶體,線程2讀取到工作記憶體中的i無效,但是線程2已經對i遞增完,也開始對i進行寫入到主記憶體操作,所以最終2個線程最終只對i進行一次遞增操作。那麼怎麼保證原子性呢,答案是加鎖。

eg

public class VolatileTest {        public static volatile int  i = 0 ;        public static ReentrantLock lock = new ReentrantLock();          public static class VTTest implements Runnable{            @Override            public void run() {                for (int j = 0; j < 1000; j++) {                    lock.lock();                    i++;    //i = i + 1;非原子操作                    System.out.println(Thread.currentThread().getId() + ":" + i);                    lock.unlock();                }            }    }        public static void main(String[] args) throws InterruptedException {        Thread[] t = new Thread[10];        for (int i = 0; i < 10; i++) {            t[i] = new Thread(new VTTest());            t[i].start();        }        for (int i = 0; i < 10; i++) {            t[i].join();        }    }}

java多線程---volatile

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.