volatile和synchronized的區別?
阿新 • • 發佈:2019-01-05
volatile 和 synchronized 都可以實現可見性。
volatile 關鍵字可以保證變數會直接從主記憶體中讀取,在寫入的時候也是直接寫入到主記憶體。
volatile 是基於 Memory Barrier (記憶體屏障)來實現的,也就是可以禁止指令重排序。如果一個變數是由 volatile 修飾的,那麼 Java 記憶體模型(JMM)在寫入這個變數之後會插入一條 writer-barrier 指令,同樣地在讀取這個變數之前也會插入一條 read-barrier 指令,這樣可以保證:
- 一個執行緒寫入一個變數a之後,其它任何執行緒訪問該變數都可以拿到最新值。
- 在寫入變數a之前的所有寫入操作對於其它執行緒也是可見的。
synchronized 關鍵字可以阻止其它執行緒獲取當前物件的監控鎖,這樣可以保證被 synchronized 關鍵字修飾的程式碼塊無法被其它執行緒訪問。
更重要的是,synchronized 關鍵字還會建立一個記憶體屏障,記憶體屏障指令保證了所有CPU操作結果都會直接刷到主存中,從而保證了操作的記憶體可見性,同時也使得先獲得這個鎖的執行緒的所有操作,都happens-before於隨後獲得這個鎖的執行緒的操作。
volatile和synchronized的區別?
- volatile本質是在告訴jvm當前變數在暫存器(工作記憶體)中的值是不確定的,需要從主存中讀取; synchronized 則是鎖定當前變數
- volatile 僅能使用在變數級別;synchronized則可以使用在變數、方法、和類級別。
- volatile僅能實現變數的修改可見性,不能保證原子性;而synchronized則可以保證變數的修改可見性和原子性
- volatile不會造成執行緒的阻塞;synchronized可能會造成執行緒的阻塞。
- volatile標記的變數不會被編譯器優化(禁止重排序);synchronized標記的變數可以被編譯器優化。