volatile介紹

volatile是輕量級的synchronized,它在多處理開發中保證了共享變量的「 可見性」。
可見性是指當一個線程修改一個共享變量時,另一個線程能讀到這個修改的值。
 
若是volatile變量修飾符使用恰當的話,它比synchronized的使用和執行成本更低。
成本低的緣由是:volatile不會引發上下文切換和調度。
 
一、volatile的定義與實現原理
Java編程語音容許線程訪問共享變量,爲了確保共享變量能被準確和一致地更新,線程應該確保經過排他鎖單獨得到這個變量。
若是一個字段聲明爲volatile,Java線程內存模型確保全部線程看到這個變量的值是一致的。
volatile如何保證可見性:
將當前處理器緩存行的數據寫回到系統內存
這個寫回內存的操做會使其餘cpu裏緩存了該內存地址的數據無效
 
爲了提升處理速度,處理器不直接和內存進行通信,而是先將系統內存的數據讀到內部緩存中後再進行操做,但操做完不知道什麼時候會寫回內存。若是對聲明瞭volatile的變量進行寫操做,JVM就會向處理器發一條lock前綴的指令,將這個變量所在緩存行的數據協會到系統內存。
在多核處理下,爲了保證各個處理器的緩存是一致的,就會實現緩存一致性協議,每一個處理經過嗅探在總線上傳播的數據來檢查本身緩存的值是否是過時了,當處理器發現本身緩存行對應的內存地址被修改時,就會將當前處理的緩存行設置爲無效狀態,當處理器對這個數據進行操做的時候,會從新從系統內存中把數據讀處處理器緩存裏。
 
二、volatile的使用優化
在JDK7中的併發包中新增了一個隊列集合類LinkedTansferQueue,它在使用volatile變量時,使用了一種追加字節的方式來優化隊列的出隊和入隊的性能。
LinkedTansferQueue這個類內部中定義了頭節點head和尾節點tail,而在其內部有一個PaddedAtomicReference類,它的做用是將共享變量追加到64位。
爲何追到64個字節會提供併發編程的效率?由於在一些處理器中,處理器的緩存L一、L2或者L3緩存的高速緩存行是64個字節的,而且不支持部分填充緩存行。這意味着在 隊列的頭節點和尾節點都不足64字節的狀況下,處理器會將頭節點和尾節點都讀取到同一個緩存行中,在多處理器每一個處理器緩存行都會緩存一樣的頭、尾節點,當一個處理器試圖修改頭節點時,會將整個緩存行鎖定,那麼在緩存一致性機制的做用下,會致使其餘處理器不能訪問本身告訴緩存行中的尾節點,而隊列的出隊和入隊操做則須要不停修改頭節點和尾節點,因此在多處理器的狀況下將會嚴重影響到隊列的出對和入隊操做。使用追加64字節的方式來填滿高速緩存行,能夠避免頭節點和尾節點同時加載到一個緩存行中,使頭、尾節點在修改時不會互相鎖定。
追加64字節的方式不適用在緩存行非64字節的處理器中。
共享變量不會被頻繁的寫(若是共享變量不被頻繁的寫,鎖的概率很是小,就沒有必要追加64字節的方式避免項目鎖定)
相關文章
相關標籤/搜索