volatile

  什麼是「可見性」編程

  • 可見性

  可見性是指一個線程修改一個共享變量時,另外一個線程能讀取到這個修改的值。數組

 

  關於volatile緩存

  • Volatile

  寫一個volatile變量時,JMM會把該線程對應的本地內存中的共享變量值刷新到主內存。併發

  一個volatile變量時,JMM會把該線程對應的本地內存置爲無效。線程接下來將從主內存中讀取共享變量。spa

  volatile會插入一個內存屏障,對volatile變量的讀或寫操做,以後的代碼不會重排序到該操做以前。線程

 

  volatile是輕量級synchronized,它保證了共享變量的「可見性」。它比synchronized的使用和執行成本更低,由於它不會引發線程上下文的切換和調度。3d

  若是一個字段被聲明爲volatile,JVM會確保全部線程按到這個變量的值是一致的。意思就是線程A修改了一個共享變量a的值從1變爲2,對線程A而言,a的值就是2。code

  JVM會確保其餘線程讀取a的值跟線程A同樣都爲2,這是一個「實時的」,即這時線程B讀取a的值必定是2。blog

                                    CPU術語定義排序

  volatile生成的彙編指令:

  Java代碼以下。
  instance = new Singleton(); // instance是volatile變量
  轉變成彙編代碼,以下。
  0x01a3de1d: movb $0×0,0×1104800(%esi);0x01a3de24: lock addl $0×0,(%esp);

  lock前綴的指令在多核處理器下會引起兩件事情:

  1)將當前處理器緩存行數據寫到系統內存

  2)這個寫回內存的操做會使在其餘CPU裏緩存了該內存地址的數據無效。

  volatile的變量進行寫操做,JVM就會向處理器發送一條Lock前綴的指令,將這個變量所在緩存行的數據寫回到系統內存。

  可是,就算寫回到內存,若是其餘處理器緩存的值仍是舊的,再執行計算操做就會有問題。

  因此,在多處理器下,爲了保證各個處理器的緩存是一致的,就會實現緩存一致性協議,

  每一個處理器經過嗅探在總線上傳播的數據來檢查本身緩存的值是否是過時了,當處理器發現本身緩存行對應的內存地址被修改。

  就會將當前處理器的緩存行設置成無效狀態,當處理器對這個數據進行修改操做的時候,會從新從系統內存中把數據讀處處理器緩存裏。

                    圖解

  目前主流的英特爾酷睿處理器的L一、L2或L3緩存的高速緩存行是64個字節寬。不支持部分填充緩存行。

  Java中,byte 是字節數據類型 ,是有符號型的,佔1 個字節;大小範圍爲-128—127 。

  char 是字符數據類型 ,是無符號型的,佔2字節(Unicode碼);大小範圍 是0—65535。 String是一個char數組。

  若是隊列的頭節點和尾節點都不足64字節的話,處理器會將它們都讀到同一個高速緩存行中,在多處理器下每一個處理器都會緩存一樣的頭、尾節點。

  當一個處理器試圖修改頭節點時,會將整個緩存行鎖定,那麼在緩存一致性機制的做用下,會致使其餘處理器不能訪問本身高速緩存中的尾節點,

  而隊列的入隊和出隊操做則須要不停修改頭節點和尾節點,因此在多處理器的狀況下將會嚴重影響到隊列的入隊和出隊效率。

  不過這種追加字節的方式在Java 7下可能不生效,由於Java 7變得更加智慧,它會淘汰或從新排列無用字段,須要使用其餘追加字節的方式。

 

    

 

 

 

參考:

《Java併發編程藝術》

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息