併發模式
為在多線程或進程間共用資源而設計的2種模式:
·主動對象設計模式將方法執行和方法調用分離開來。目的是加強並發和簡化對駐留在自身控制線程中的對象的同步訪問。
·監視器對象設計模式同步化並發方法的執行,以確保同一時刻在對象內部只有一個方法運行。它也允許對象的方法協作調度方法的執行順序。
下面2種模式定義了高層並發體繫結構:
·半同步/半非同步體繫結構模式將並發系統中的同步和非同步進程分離,簡化了編程而又不影響效能。該模式引入兩個通訊層,一個處理同步服務,另一個處理非同步服務。還有一個排隊層協調非同步層和同步層服務之間的通訊。
·領導者/追隨者體繫結構模式提供了一種高效的並行存取模型,多個線程依次共用一組事件來源,從而對事件來源中產生的服務要求進行檢測、多路分解、分配和處理。對由緩衝池的線程進行處理的請求沒有同步化或沒有排序的約束時,領導者/追隨者模式可以代替半同步/半非同步和主動對象模式,以改進效能。
為解決某些並發的內在複雜性提供另一種策略:
·線程特定的儲存空間設計模式允許多個線程使用一個“邏輯上全域的”訪問點檢索某一本機物件,而不會導致訪問對象時發生加鎖開鎖。在某種程度上,這種模式可以看做其他模式的“對立面”,因為它通過防止進程間的資源共用來實現複雜的內部並發機制。
5.1主動對象(Active Object)
1.問題
許多應用程式受益於使用並發對象而改進了服務品質,然而,對象並行執行階段,如果這些對象被多個客戶機線程共用和修改,則必須同步化對它們的方法和資料的訪問,這時產生三個強制條件:
1)並發地調用對象的處理密集的方法不應無限期地阻塞整個進程,並因些降低其他並發對象的服務品質。
2)應該很容易編程實現對共用對象的同步化訪問。特別地,對共用對象的客戶機方法調用的序列化和調度都應是透明的,該共用對象具有同步約束。
3)應用程式的設計應透明地使用在硬體/軟體平台提供的並行機制。
2.解決方案
對受以上強制條件約束的對象而言,將其方法調用與執行分離。方法調用應該發生在客戶機的控制線程中,而方法執行應發生在另一個線程中。此外,要將這種分離設計成使客戶機線程看上去像調用普通的方法一樣。
細節:代理(Proxy)代表主動對象的介面。服務者(Servant)提供了主動對象的實現。代理和服務者在不同的線程中運行,因此方法調用和方法執行可以並發執行。代理在客戶機線程中運行,而服務者在另一個線程中運行。
在運行時代理將客戶機的方法調用轉換為方法請求,發送器將方法請求儲存在一個啟用表(Activation List)中。發送器的事件迴圈和服務者在同一線程中連續運行,將方法請求從啟用表隊列中取出並將它們分配給服務者。客戶機可以通過代理返回的前景得到方法執行的結果。
3.結構
代理提供一個介面允許客戶機調用主動對象的公用可訪問的方法。代理的使用允許應該程式使用標準的強型別語言特性編程,而不是線上程間傳遞弱類型的訊息。代理駐留在客戶機線程中。
客戶機調用一個由代理定義的方法時,它觸發方法請求(Method Request)對象的建構函式方法請求包括語境資訊(如方法的參數),執行指定方法調用和向客戶機返回結果時需要這些資訊。方法請求類定義了一個執行主動對象方法的介面。介面也包括可以用來確定某一方法請求是否可執行檔哨兵方法。對由主動對象中需要同步化訪問的代理所提供的每個公用方法,從方法請求類中派生出具體方法請求類(Concrete MethodRequest)。
代理將它建立的具體方法請求插入一個啟用表(Activation List)。該表包含一個待處理的由代理建立的方法請求組成的有限緩衝區,並跟蹤哪些方法請求可執行。啟用表將駐留代理的客戶機線程和執行服務的線程分開,這樣兩個線程可以同時運行。因此,啟用表的內部狀態必須序列化,以防對它同時訪問。
發送器(Scheduler)在其客戶機代理之外的線程中運行,也就是主動對象的線程。它決定下一次對主動對象將執行哪一個方法請求。這一調度決策基於不同的準則(如排序一對主動對象調用方法的順序),或者基於主動對象的某些屬性(如它的狀態)。發送器可以使用方法請求哨兵評估這些屬性,方法請求哨兵確定何時可以執行這些方法請求。發送器用啟用表管理待處理的方法請求。當客戶機調用其方法時,代理將方法請求插入啟用表中。
服務者被建模為主動對象,其中定義了其行為和狀態。服務者實現的方法對應於代理介面和由代理建立的方法請求。服務者可能還包含其他謂詞方法,方法請求能夠用這些謂詞方法類實現哨兵。在發送器執行與之關聯的方法請求時調用服務者方法。因而,它在發送器的線程中執行。
當客戶機調用代理上的方法時,會接收到一個前景(future)。該前景允許客戶機在服務者完成方法的執行後獲得方法調用的結果。每個前景都為被調用的方法保留一定的空間,存放方法調用的結果。當客戶機想得到該結果時,它可以與前景匯合(rendezvous),阻塞或輪詢直到結果被計算出來並存入前景。
4.實現
1)實現服務者。服務者被建模為主動對象,其中定義了其行為和狀態。另外,服務者還可能包含用來確定何時執行方法請求的謂詞方法。
2)實現調用的基礎設施。在這一活動中,描述了客戶機調用主動對象的方法所必需的基礎設施。這種基礎設施由建立方法請求的代理構成。
2.1)實現代理。代理為客戶機提供了訪問服務者方法的介面。對於客戶機的每次方法調用,代理都建立一個具體的方法請求。每一方法請求是方法語境的抽象,也稱為方法閉包(closure)。一般情況下該語境包括方法參數,到被方法應用的服務者的綁定,結果的前景以及執行方法請求的代碼。
2.2)實現方法請求。方法請求可以看做一個命令對象,方法請求類聲明了一個被所有具體方法請求使用的介面,它為發送器提供了一個統一的介面,而不用瞭解如何評估同步約束或者如何觸發具體方法請求的執行。
3)實現啟用表。每個方法請求都插入到一個啟用表中。該表可以實現為同步限界緩衝區,該緩衝區由客戶機線程和運行主動對象發送器及服務者的線程共用。啟用表也可以提供一個健壯的迭代器,發送器可以遍曆和刪除它的元素。
4)實現主動對象的發送器。發送器是一個命令處理常式。用於管理啟用表和執行滿足同步約束的未處理的方法請求。發送器的公用介面通常提供兩個方法,一個被代理用於將方法請求插入到啟用表中。另一個用於將方法請求分配給服務者。
5)確定匯合和傳回值策略。匯合策略確定客戶機如何從對主動對象調用的方法中得到傳回值。在一個線程中執行的主動物件服務者向另一個線程中啟動並執行調用該方法的客戶程式傳遞傳回值時,匯合發生。實現主動對象模式通常選擇如下匯合和傳回值策略:
·同步等待。在代理中同步阻塞客戶機線程,直到發送器分配方法請求並且得到結果並儲存到前景中。
·同步定時等待。阻塞有限的時間,並且如果主動對象的發送器在規定時間內未能分配方法請求則失敗。如果逾時為零,客戶機線程就“輪詢”,也就是在發送器不能將它立即分配時可返回到調用者而不需將方法請求放入隊列。
·非同步。將方法調用放入隊列並且立即將控制返回給客戶機。如果方法是一個產生結果的雙向調用,則必須使用某些形式的前景以提供對值的同步化訪問,或者在調用失敗時對錯誤狀態的同步化訪問。
5.結論
優點:
1)增強了應用程式的並發性,簡化了同步的複雜性。通過允許客戶機線程和非同步方法呼叫同時執行而增加了應用程式的並發性。通過使用發送器而簡化了同步的複雜性,發送器計算同步約束,以保證根據其狀態對服務者進行串列訪問。
2)透明地應用可用的並行性。如果硬體和軟體平台能有效地支援多CPU,那麼該模式可以允許多個主動對象並行地執行,是否並存執行僅僅取決於它們的同步約束。
3)方法的執行順序可以和方法的調用順序不同。非同步呼叫的方法是根據由方法的哨兵和調度策略定義的同步機制而執行的。因此,方法執行的順序可以與方法調用的順序不同。這種分離有助於提高應用程式的效能和靈活性。
不足:
1)效能開銷。根據主動對象的發送器的實現方式不同,當調度和執行主動對象方法調用時可能引起語境切換,同步化和資料移動開銷。一般來說,主動對象模式最適用於相對粗粒度的對象。
2)複雜的調試。因為各種主動對象的發送器和底層的作業系統線程發送器的並發性和不確定性。所以很難調試使用主動對象模式的程式。