同步模式
C++慣用法定界加鎖(Scoped Locking)能確保當控制進入到某一個範圍時,自動獲得鎖,而當控制離開該範圍時,自動釋放鎖,不管從該範圍返回的路徑是什麼。
策略化加鎖(Strategized Locking)設計模式是策略模式的一種特例,它把同步機制參數化,這一機制保護臨界區免受並發訪問。
安全執行緒介面(Thread-Safe Interface)設計模式使加鎖的開銷減至最少,確保組件內部的方法調用不會因為要再次獲得一個組件已經擁有的鎖而“自死結”。
如果程式執行期間臨界區代碼只能以安全執行緒的方式獲得一次鎖,雙檢查加鎖最佳化(Double-Checked Locking Optimization)設計模式能夠降低爭用和同步開銷。
4.1定界加鎖(Scoped Locking)
1.問題
必須保護不能被並發執行的代碼,方法是使用某些類型的鎖,當控制進入或離開一個臨界區時分別獲得或者釋放這種鎖。但是,如果程式員必須顯式地獲得或釋放鎖,就難以保證在經過該代碼的所有路徑上鎖都被釋放了。
2.解決方案
定義一個哨兵(guard)類,當控制進入一個地區時,哨兵類的建構函式自動獲得一個鎖;當控制離開這個地區時,哨兵類的解構函式自動釋放該鎖。將哨兵類執行個體化,以在定義臨界區的方法和塊地區中獲得或釋放鎖。
3.實現
1)定義一個哨兵類。其建構函式和解構函式分別獲得和釋放某種類型的鎖。哨兵類的建構函式中存放一個指向鎖的指標或對鎖的引用,據此獲得該鎖。解構函式使用由建構函式儲存的指標或引用釋放該鎖。
2)讓臨界區對應於哨兵對象的範圍和生命期。要避免並發訪問臨界區,應指定一個地區,並由該地區的第一條語句在棧中建立一個哨兵對象。哨兵類的建構函式自動獲得該鎖。在離開臨界地區時,自動調用釋放該鎖的解構函式。根據C++解構函式的語義,即使在臨界區中拋出一個異常,這個保護鎖也會被釋放。
4.結論
優點:
1)增加了健壯性。通過使用這個方法,當控制進入或離開由C++方法和塊地區定義的臨界區時,會自動地獲得和釋放鎖。這種方法消除了與同步和多線程有關的常見的編程錯誤,從而提高了並發應用程式的健壯性。
不足:
1)遞迴使用時可以發生死結。如果一個使用定界加鎖慣用法的方法遞迴地調用自己,當該鎖不是一個“遞迴”的互斥時,就會發生“自死結”。
2)受與語言相關的語義的限制。定界加鎖慣用法是基於C++語言特性,因此不會和作業系統有關的系統調用整合起來。這樣當進程或線程在一個受保護的臨界區內部失敗或退出時,鎖就不能自動地釋放。
3)過多的編譯器警告。 定界加鎖慣用法定義了一個在一個地區中沒有被顯式使用的哨兵對象,因為其解構函式隱含地釋放鎖。不幸的是,當在某地區定義了哨兵而沒有顯式地使用到哨兵時,一些C++編譯器會顯示"statement has no effect"的警告資訊。