寫在前面:
- 你好,歡迎關注!
- 我熱愛技術,熱愛分享,熱愛生活, 我始終相信:技術是開源的,知識是共享的!
- 博客裏面的內容大部分均爲原創,是自己日常的學習記錄和總結,便於自己在後面的時間裏回顧,當然也是希望可以分享 自己的知識。如果你覺得還可以的話不妨關注一下,我們共同進步!
- 個人除了分享博客之外,也喜歡看書,寫一點日常雜文和心情分享,如果你感興趣,也可以關注關注!
- 公衆號:傲驕鹿先生
ourInstance = new Singleton();
創建了一個對象。這一行代碼可以分解爲如下的3行僞代碼:
memory = allocate(); // 1:分配對象的內存空間
ctorInstance(memory); // 2:初始化對象
ourInstance = memory; // 3:設置ourInstance 指向剛分配的內存地址
2和3之間重排序之後的執行時序如下:
memory = allocate(); // 1:分配對象的內存空間
instance = memory; // 3:設置instance指向剛分配的內存地址
// 注意,此時對象還沒有被初始化!
ctorInstance(memory); // 2:初始化對象
2和3之間雖然被重排序了,但這個重排序並不會違反intra-thread semantics。這個重排序在沒有改變單線程程序執行結果的前提下,可以提高程序的執行性能。
-
只需要做一點小的修改(把instance聲明爲volatile型),就可以實現線程安全的延遲初始化。
-
當聲明對象的引用爲volatile後,2和3之間的重排序,在多線程環境中將會被禁止。
private volatile static Instance instance;
Volatile的重排序規則:
-
當第二個操作是volatile寫時,不管第一個操作是什麼,都不能重排序。這個規則確保volatile寫之前的操作不會被編譯器重排序到volatile寫之
-
當第一個操作是volatile讀時,不管第二個操作是什麼,都不能重排序。這個規則確保volatile讀之後的操作不會被編譯器重排序到volatile讀之前。
-
當第一個操作是volatile寫,第二個操作是volatile讀時,不能重排序。
-
在每個volatile寫操作的前面插入一個StoreStore屏障。
-
在每個volatile寫操作的後面插入一個StoreLoad屏障。
-
在每個volatile讀操作的後面插入一個LoadLoad屏障。
-
在每個volatile讀操作的後面插入一個LoadStore屏障。
b. 基於類初始化的解決方案--即允許2和3重排序,但不允許其他線程“看到”這個重排序