3.1 主動對象
Active 對像是一種設計模式,它將方法的執行線程與調用它的線程分開。此模式的目的是使用異步方法調用和請求處理調度程序提供並行執行。
簡化版:
經典變體:
這個模板有六個元素:
- 為客戶端的公共方法提供接口的代理對象。
- 定義活動對象訪問方法的接口。
- 來自客戶端的傳入請求列表。
- 確定查詢執行順序的調度程序。
- 活動對象方法的實現。
- 客戶端接收結果的回調過程或變量。
3.2 鎖定
Lock 模式是一種同步機制,允許在多個線程之間獨占訪問共享資源。鎖是執行並發控制策略的一種方式。
基本上,使用軟鎖,假設每個線程在訪問相應的共享資源之前嘗試“獲取鎖”。
然而,一些系統提供了強制鎖定機制,通過在試圖獲得訪問權限的線程上拋出異常來中止對鎖定資源的未授權訪問嘗試。
信號量是最簡單的鎖類型。在數據訪問方面,不區分訪問模式:共享(只讀)或獨占(讀寫)。在共享模式下,多個線程可以請求一個鎖來訪問只讀模式下的數據。獨占訪問模式也用於更新和刪除算法。
鎖的類型通過阻止線程繼續執行的策略來區分。在大多數實現中,鎖定請求會阻止線程繼續執行,直到鎖定的資源可用。
自旋鎖是一種在循環中等待直到訪問被授予的鎖。如果線程等待鎖的時間很短,這樣的鎖會非常有效,這可以避免過度重新安排線程。如果其中一個線程長時間持有鎖,則等待訪問的成本將很高。
要有效實現鎖定機制,需要硬件層面的支持。硬件支持可以實現為一個或多個原子操作,例如“測試和設置”、“獲取和添加”或“比較和交換”。此類指令允許您不間斷地檢查鎖是否空閒,如果是,則獲取鎖。
3.3 監控
Monitor 模式是一種高級進程交互和同步機制,提供對共享資源的訪問。一種使用公共資源(通常是硬件或一組變量)同步兩個或多個計算機任務的方法。
在基於監視器的多任務處理中,編譯器或解釋器透明地將鎖定-解鎖代碼插入到適當格式的例程中,對程序員透明,從而使程序員免於顯式調用同步原語。
監控器包括:
- 一組與共享資源交互的過程
- 互斥體
- 與此資源關聯的變量
- 定義條件以避免競爭條件的不變量
監控程序在開始工作之前獲取互斥鎖,並持有它直到程序退出或等待特定條件。如果每個過程在釋放互斥量之前保證不變量為真,則沒有任務可以在競爭條件下獲取資源。
這就是synchronized運算符在 Java 中與wait()
and方法一起工作的方式notify()
。
3.4 雙重檢查鎖定
雙重檢查鎖定是一種並行設計模式,旨在減少獲取鎖的開銷。
首先,在沒有任何同步的情況下檢查阻塞條件。僅當檢查結果表明它需要獲取鎖時,線程才會嘗試獲取鎖。
//Double-Checked Locking
public final class Singleton {
private static Singleton instance; //Don't forget volatile modifier
public static Singleton getInstance() {
if (instance == null) { //Read
synchronized (Singleton.class) { //
if (instance == null) { //Read Write
instance = new Singleton(); //
}
}
}
}
如何在線程安全的環境中創建單例對象?
public static Singleton getInstance() {
if (instance == null)
instance = new Singleton();
}
如果你從不同的線程創建一個Singleton對象,那麼可能會出現同時創建幾個對象的情況,這是不可接受的。因此,將對象創建包裝在同步語句中是合理的。
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
這種方法會奏效,但它有一個小缺點。對象創建後,以後每次嘗試獲取它時,都會在synchronized塊中進行一次檢查,這意味著當前線程和與之連接的一切都將被鎖定。所以這段代碼可以稍微優化一下:
public static Singleton getInstance() {
if (instance != null)
return instance;
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
在某些語言和/或某些機器上,無法安全地實現此模式。因此,它有時被稱為反模式。這樣的特性導致了Java內存模型和C++內存模型中出現了“happens before”的嚴格順序關係。
它通常用於減少在多線程程序中實現惰性初始化的開銷,例如 Singleton 設計模式。在變量的惰性初始化中,初始化被推遲到計算中需要變量的值時。
3.5 調度器
Scheduler是一種並行設計模式,它提供了一種實現調度策略的機制,但獨立於任何特定的策略。使用顯式指定等待線程序列的對象,控制線程執行順序代碼的順序。