1. 程式人生 > >淺談volatile與automicInteger

淺談volatile與automicInteger

在併發環境中有三個因素需要慎重考量,原子性、可見性、有序性。
   voatile 保證了有序性(防止指令衝排序)和變數的記憶體可見性(每次都強制取主存資料),每次取到volatile變數一定是最新的
   volatile主要用於解決可見性,它修飾變數,相當於對當前語句前後加上了“記憶體柵欄”。使當前程式碼之前的程式碼不會被重排到當前程式碼之後,當 前程式碼之後的指令不會被重排到當前程式碼之前,一定程度保證了有序性。而volatile最主要的作用是使修改volatile修飾的變數值時會使所有執行緒中的快取失效,並強制寫入公共主存,保證了各個執行緒的一致。可以看做是輕量級的Synchronized。詳情可參看:
automicXXX主要用於解決原子性,有一個很經典的問題:i++是原子性的操作碼?答案是不是,它其實是兩步操作,一步是取i的值,一步是++。在取值之後如果有另外的執行緒去修改這個值,那麼當前執行緒的i值就是舊資料,會影響最後的運算結果。使用automicXXX就可以非阻塞、保證原子性的對資料進行增減操作。詳情可參看:http://ifeve.com/java-atomic/


volatile原理:
    1.volatile可以保證執行緒可見性,且提供了一定的有序性,但無法保證原子性。
        1.保證可見性,不保證原子性
2.禁止指令重排序
    2.JVM底層,volatile採用 "記憶體屏障" 來實現
    
    可見性實現:
             可見性是指當多個執行緒訪問同一個變數時,一個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值
     synchronize和鎖都可以保證可見性。


             執行緒本身並不直接與主存進行資料交換,而是通過執行緒的工作記憶體來完成相應的操作  ---  執行緒間資料不可見的根本原因!!!
     volatile實現可見性,直接從這方面入手,
        1.修改volatile變數時,會強制將修改後的值重新整理到主記憶體中
2.修改volatile變數後,會導致其他執行緒工作記憶體中對應的變數值失效,再讀取該變數值時,要重新從主記憶體中讀取


    有序性實現:
             關於重排序:
          編譯器重排序:不改變單執行緒語義的前提下,可以重新安排語句的執行順序
  處理器重排序:不存在資料依賴性,處理器可以改變語句對應機器指令的執行順序
             指令重排序對單執行緒無影響,但會影響多執行緒的正確性,
     JVM如何禁止重排序?
           happens-before 原則:保證程式的有序性
---------------------
作者:拉薩之虎2012
來源:CSDN
原文:https://blog.csdn.net/dan1289095756/article/details/80803977
版權宣告:本文為博主原創文章,轉載請附上博文連結!