java基礎---多線程---volatile詳解

===volatile做用?volatile的實現原理是什麼呢?lock前綴的效果是什麼呢?
volatile的做用:
1.可見性。一個線程對volatile變量進行寫操做以後,其餘線程都可以看到。
2.原子性。單個volatile變量的讀寫具備原子性,可是複合操做不知足原子性。
用來修飾變量
對volatile修飾的變量進行修改操做的時候,會在操做指令以前添加上LOCK前綴。
LOCK前綴的效果是:命名    
1.當前處理器緩存行的數據會寫回到系統內存的時候會先獲取總線,同時其餘cpu阻塞。
2.保證緩存一致性,會使得其餘CPU緩存的數據失效。由於其餘cpu會不斷嗅探總線,一發現本身緩存的數據被修改了就作失效標記。被標記以後要用的時候會從新從系統內存拿。
緩存一致性可能存在的問題:大量緩存一致性流量
volatile自己的內存語義
線程寫volatile變量至關於給接下來要讀取這個變量的線程發送消息。
線程讀volatile變量至關於接收以前某個線程發出的消息。
兩種都要通過主內存這個中間橋樑。
volatile讀寫防止指令重排序
可以創建一個內存屏障,必定程度上禁止指令重排序。重排序的時候不會把前面的讀寫指令重排序影響到volatile寫,同時也不會把後面的指令放在內存屏障前面。同時保證在執行到內存屏障這條指令的時候,前面的操做都是已經完成的。
 
CPU是如何保證原子性的?
1.加總線鎖。經過Lock#指令鎖住總線,防止其餘處理器同時修改內存。
2.加緩存鎖定。經過緩存一致性讓其餘cpu的緩存數據失效。
java中如何實現原子性
1.使用CAS
2.使用重量級鎖,可是這種鎖的獲取和釋放仍是使用CAS,由於是須要進入隊列的。重量級鎖也有同步隊列。
 
 
volatile在單例模式中的應用
private valitle static Instance instance;
public static Instance getInstance(){
    if (instance == null){
        synchronized(Instance.class){
            if (instance == null) {
                instance = new Instance(); //首先這步驟是複合操做
            }
        }
    }
    return instance;
}
若是第一個線程進來執行到初始化這步了:
由於中間實例化的步驟是一個複合操做,至關於三個步驟
1.分配內存空間
2.初始化
3.引用指向
可是因爲單線程狀況下會出現指令重排序,23顛倒了,因此引用先指向了那個還沒初始化的內存空間。
這個時候另外一個線程進來可以看到instance非空那麼就直接返回了,可是其實尚未初始化完成,因此出錯。
 
使用volatile修飾instance就是爲了防止指令衝排序,由於最後一步引用指向至關於一個volatile寫操做,經過內存屏障就可以防止指令重排序了。
相關文章
相關標籤/搜索