創建單例的正確姿勢

#define barrier() __asm__ volatile("lwsync")
volatile T* pInst = 0; //volatile關鍵字阻止編譯器為了優化編譯效率而調整了該變量的匯編指令順序,簡單來說就是禁止進行指令重排序。
T* getInstance()
{
  lock();
  if (!pInst) //鎖內再加一個條件語句降低lock調用開銷
  {
    T* temp = new T();
    barrier(); //阻止CPU因優化而動態調度調整指令順序
    pInst = temp;
  }
  unlock();
  return pInst;
}

T* temp = new T();這一步驟其實由三小步構成:

(1)分配內存;
(2)在內存位置調用構造函數;
(3)將內存地址賦給指針。

在CPU動態調度優化時,可能發生改變以上三步順序的情況,從1-2-3變成了1-3-2。如果1-3-2這種情況發生了,此時在(3)執行完后如果外部調用方緊接著使用pInst指針去調用該單例的某個實例方法,而該指針指向的內存區域中的構造函數尚未執行完,這個時間差就可能造成方法調用失敗。

barrier()的插入就是可以保證temp在完全執行完畢后再執行下一步的賦值指令,無論前面是否存在CPU調整指令順序的情況。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容