DCL單例為什么要加Volatile


拿一個對象創建賦值來說

class T{
  int  elem = 1;
}

T t = new T();

上段代碼轉換成匯編碼為:

0  new  #2 <T>
3  dup
4  invokespecial  #3  <T.<init>>
7  astore_1
8  return 

從匯編碼中可以看出,0行為對象開辟了一個內存空間,該內存的成員區包含整形變量elem,值初始為0(如果是引用或者指針變量則為空)。3行dup指令是在棧中復制一個對象的引用(在new的時候該棧中已經存在一個,執行dup后也就是兩個了),第4行執行初始化,為對象成員變量賦值,這個時候會消耗一個引用並將它從棧中pop掉,這也是為什么要dup的原因。7行指令是將棧中的引用賦值給對象t,並在棧中pop掉該引用。8然后return。這個是整個匯編語言按源代碼執行得過程。

但是cpu本質上得亂序執行,可能造成指令得重排,特別是在初始化對象指令上花費時間較多,可能進行了如下重排:

0  new  #2 <T>
3  dup
7  astore_1
4  invokespecial  #3  <T.<init>>
8  return 

指令第7行可能在cpu執行是與第4行重排,那么當線程一從0開始執行,執行到第7行得時候將未初始化得對象得引用賦值給t,如果線程一掛起,線程二發現t的引用不為空在執行下面代碼:if (t != null)  xxxx->使用了半初始化得對象。會造成后續程序出錯。所以用volatile來禁止指令重排來保證單例線程安全。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM