4.2策略化加鎖(Strategized Locking)
1.問題
運行在多線程環境中的組件必須保護其臨界區不被客戶機並發訪問。同步機制與組件功能的整合需要解決以下兩個強制條件:
1)不同的應用程式可能要求不同的同步策略,如互斥、讀寫鎖或資訊燈。因此,應該可以按照具體應用的需求定製組件的同步機制。
2)加入新的功能和隱錯修正應很容易。特別為避免“版本混亂”應始終將這些變化一致地自動地應用於組件系列的所有成員上。
2.解決方案
將組件的同步特性變成“可插”的類型,用這種方式將組件的同步特性參數化。每種類型將特定的同步化策略對象化,同步策略包括互斥、讀寫鎖、號誌或“空”鎖等。將這些可插的類型的執行個體定義為包含在組件中的對象,該組件可以使用這些對象有效地使其方法實現同步化。
3.實現
1)不考慮組件的同步特性,定義組件的介面和實現。
2)將加鎖機制策略化。許多組件有相對簡單的同步特性,可以使用常用的加鎖策略,如互斥和號誌等實現這些同步特性。可以統一地使用多態性或參數化型別將同步特性策略化。一般來說,如果直到運行時才知道加鎖策略,就應該使用多態性。相反,如果在編譯時間就知道加鎖策略,那就應該使用參數化型別。參數化型別有運行效率高的特點,而多態性有運行時可擴充的潛力。
假設使用定界加鎖慣用法,策略化鎖包括兩個子活動:
2.1)為加鎖機制定義一個抽象介面。為了使組件能使用不同的加鎖機制,這些機制的所有具體實現應該使用具有共同特徵的抽象介面,用於在多態性或參數化型別的基礎上擷取和釋放鎖。
2.2)使用定界加鎖慣用法定義一個用同步特徵將其策略化的哨兵類。這種設計遵循策略模式。其中,哨兵類作為擁有某一特殊鎖的語境,而具體鎖提供策略。
3)更新群組件的介面和實現。在策略化同步機制後,組件可以使用這些機制,通過顯式地獲得或釋放一個鎖,或者使用定義的哨兵類來保護臨界區。
4)修改組件實現以避免死結和刪除不必要的加鎖開銷。如果組件間存在方法調用,那麼開發人員必須仔細地設計其組件實現,以避免自死結和不必要的同步開銷。
5)定義一組具有統一介面的加鎖策略,這些策略可以支援各種應用特定的並發設計。
4.結論
優點:
1)增加靈活性和個人化。為特定的並行存取模型配置和定製一個組件是很容易的,因為組件的同步特性被策略化了。如果對於一種新的並行存取模型沒有合適的加鎖策略可用,可以在不影響已有代碼的情況下擴充新的加鎖策略。
2)降低組件維護的代價。使用原則化加鎖模式很容易改進組件和隱錯修正,因為對於各種並行存取模型只有一個實現,而不是每種並行存取模型對應一個獨立的實現。將問題集中的方法有助於減少版本混亂。
3)改善重用性。用這種模式實現的組件不太依賴於具體的同步機制。
不足:
1)強行(obtrusive)加鎖。
2)過分工程化(over-engineering)。