單例模式的雙重校驗鎖模式 的知識點 解讀


public class Singleton {
private volatile static Singleton uniqueSingleton;

private Singleton() {
}

public Singleton getInstance() {
if (null == uniqueSingleton) {
synchronized (Singleton.class) {
if (null == uniqueSingleton) {
uniqueSingleton = new Singleton();
}
}
}
return uniqueSingleton;
}
}


1 單例模式 何時懶漢 何時餓漢
懶漢 延遲加載 一些很耗資源的(時間 io cpu 內存)操作 可以用到時 加載 初始化
餓漢 簡單的實現 可以保證線程安全的單例


2 去掉 volatile 怎樣
A a=new A();
一行代碼 其實翻譯成機器碼(可以理解成 匯編碼)其實是多個指令
至少兩步
一 分配內存 初始化
二 內存地址和引用 關聯 (棧 存 引用;堆 存 實例化的對象)
這兩步其實 是無序的
如果 第一個線程 進去 第一個判空 為空 去new 但是 先走了第二步 停下 此時 第二個線程 進去 就會 直接
return uniqueSingleton; 一個未初始化完成的對象 去用可能就會有問題 比如 里面有對象 啥的 空指針

//volatile vs synchronized
volatile 保證多線程下 可見性 有序性 但不保證原子性
jdk 一直在對鎖優化 所以 volatile 不一定比 synchronized 快多少 但是多少會快  
首先 實現的機制不一樣 synchronized 基於 鎖的互斥 而且 volatile 沒保證原子性 多少會快
// 擴展 : 什么時候用 volatile
不存在原子性 或者 不需要保證原子性
比如 一寫多讀

注意 jdk 1.5 及之后 才保證有序


3 synchronized 參考:https://blog.csdn.net/zjy15203167987/article/details/82531772
一個對象只有一把鎖,一個線程獲取了該對象的鎖之后,其他線程無法獲取該對象的鎖,就不能訪問該對象的其他synchronized實例方法,但是可以訪問非synchronized修飾的方法(待驗證)
修飾代碼塊 相對修飾方法的好處 修飾代碼塊 鎖的東西更少 效率相對較高
修飾非static方法和修飾代碼塊 一樣 其實鎖的也是對象
代碼塊鎖對象的三種方式(待驗證 : A類中的代碼塊 怎么去鎖B對象 B類)

class A{
  static A a=new A();
  synchronized(a){
  }
}

synchronized(this){
}
(待研究 鎖的是 對象 還是類)
synchronized(A.class){
}

4 為啥不直接 synchronized 修飾方法
慢 因為只有第一次才需要鎖
后面new 后 不需要鎖 直接return


 


免責聲明!

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



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