靜態條件問題:
還沒做好準備卻收到了通知
notify是喚醒乙個執行緒
notifyall是喚醒所有程序
(一般更推薦notify)
wait和sleep的對比[?]
這倆完全沒有關係
sleep是讓當前執行緒休眠
wait/notify機制一定程度的影響執行緒排程.
單例模式 是一種常見的"設計模式" ?設計模式:軟體開發中,涉及到的場景有很多
也會有很多變化(軟體開發是一件比較複雜的事情)
很多新手如果不加限制亂開發
此時往往就會陷入到很多很多的問題中
於是大佬們就把常見的場景的一些常見解決方案整理成了乙份棋譜
後續新手只要按照棋譜來開發.此時就不會差到哪去
這份棋譜就是設計模式
**中的有些概念,不應該存在多個例項,此時應該使用單例模式來解決
保證指定的類只能有乙個例項(如果嘗試建立多個例項,直接編譯報錯)
兩種典型的方式實現單例模式:
1.餓漢模式
只要類被載入,就會立刻例項化,singleton例項
後續無論怎麼操作,只要嚴格使用getinstance,就不會出現其他的例項
剛才的new沒報錯是因為singleton類是內部類
所以類可以訪問內部類的成員的
**:
class
singleton1
// static 和 類相關, 和 例項無關~ 類在記憶體中只有乙份, static 成員也就只有乙份.
public
static singleton1 getinstance()
}public
class
ehan
}
2.懶漢模式
使用懶漢模式的時候,singleton類被載入時,不會立刻例項化
等到第一次使用這個例項的時候在例項化
如果**一整場都沒有呼叫getinstance
此時例項化的過程也就被省略掉了
這也被叫做"延時載入"
一般認為"懶漢模式"比"餓漢模式"效率更高
因為懶漢模式有很大可能是例項用不到,此時就節省了例項化的開銷
**:
class
singleton2
public
static singleton2 getinstance()
return instance;}}
public
class
lanhan
}
1. 那麼單例模式和執行緒有什麼關係呢?涉及到執行緒安全問題?
剛才這兩種單例模式的實現模式,是否是執行緒安全的?
(什麼樣的情況會導致執行緒不安全呢?)
現成的排程是搶占實質性
修改操作不是原子的
多執行緒同時修改同乙個變數
記憶體可見性…
類載入只有一次機會,不可能併發執行
對於餓漢模式來說,多執行緒同時呼叫getinstance
由於getinstance只做了一件事:讀取instance
所以相當於多個執行緒在同時讀取同乙個變數,不存在修改
所以他是執行緒安全的
對於懶漢模式來說,多執行緒同時呼叫getinstance
由於getinstance做了四件事
讀取instance內容
判斷instance內容是否為空
如果instance為null,就new例項 => 會修改instance的值
返回例項位址.
併發執行時:
執行緒1 執行緒2
讀取instance內容 讀取instance內容
判斷instance內容是否為空 判斷instance內容是否為空
如果instance為null,就new例項 如果instance為null,就new例項
返回例項位址 返回例項位址
此時這個類已經不是單例了,而是new了兩次,如果執行緒數目更多
就可能會new更多的次數.
不再符合單例模式的要求,就認為**是錯誤的
所以說懶漢模式是執行緒不安全的(涉及到兩個執行緒同時去修改同乙個變數)
如果要是已經把例項建立好了,後面再去併發呼叫getinstance就是執行緒安全的
執行緒安全的懶漢模式:
class
singleton3
public
static singleton3 getinstance()
}return instance;
}}
加鎖以後:
執行緒1: 執行緒2
加鎖 等待中..
讀取instance 等待中...
判斷instance內容是否為空 ...
為null就new instance ...
釋放鎖 獲取鎖(instance此時一定是非null)
返回 讀取instance
兩種寫法都可以,但是下面的寫法,鎖粒度更大 (鎖中包含的**越多)
就認為粒度越大
---但是當例項建立好了以後,此時就不再設計執行緒安全問題
2. 在上面的**中,哪怕例項已經建立好了,每次呼叫getinstance還是會涉及到加鎖,而這裡加鎖解鎖已經不再需要了
我們需要的是只有例項化之前呼叫的時候加鎖,後面不加鎖~
因此再次進行修改:
class
singleton3
public
static singleton3 getinstance()
}}return instance;
}}
例項化前:
執行緒1 執行緒2
讀取instancce 讀取instancce
判斷instance為空 判斷instance為空
加鎖(成功) 加鎖(失敗)
讀取instancce 等待
判斷instance為空
發現instance為空 new例項
釋放鎖返回 加鎖成功
例項化後:
執行緒1 執行緒2
讀取instancce 讀取instancce
判斷instance非空 判斷instance非空
...
3. 但是~
上面的**仍然有問題
先加鎖的執行緒在修改
後加鎖的執行緒在讀取
那麼就涉及到記憶體可見性問題,因為僅僅是讀取操作,可能被編譯器優化
所以要在instance前加volatile保證記憶體可見性
class
singleton3
public
static singleton3 getinstance()
}}return instance;
}}
最終:?
為了保證執行緒安全,涉
及到三個要點:
1.加鎖 保證執行緒安全
2.雙重 if 保證效率
3.volatil 避免記憶體可見性引來的問題
設計模式 單例模式
單例模式 singleton pattern 是乙個比較簡單的模式,其定義如下 ensure a class has only one instance,and provide a golbal point of acess to it.確保某乙個類只有乙個例項,而且自行例項化並且向整個系統提供這個...
設計模式 單例模式
class testsingleton static public function instance return self testsingleton private function clone public function setsinvar sinvar public function ...
設計模式 單例模式
單例模式的目的是保證類在系統中只被例項化一次,由該唯一的例項來為系統提供服務.單例模式主要用於保證服務的統一,比如獲取統一的編號服務,模仿oracle的序列生成等.但單例的使用需要謹慎,特別是在需要作負載均衡的地方,因為這種程式級的單例模式實際上只能保證在乙個應用中為單例.如果被多個應用載入,還是會...