🔍目的
主要目的是為多個線程或進程提供一種結構化和受控的方式來安全地訪問和操作共享資源,例如變量、數據結構或代碼的關鍵部分,而不會導致沖突或競爭條件。
🔍解釋
通俗描述
監視器模式用于強制對數據進行單線程訪問。 一次只允許一個線程在監視器對象內執行代碼。
維基百科
在并發編程(也稱為并行編程)中,監視器是一種同步構造,它允許線程具有互斥性和等待(阻止)特定條件變為假的能力。 監視器還具有向其他線程發出信號通知其條件已滿足的機制。
程序示例
考慮有一家銀行通過轉賬方式將錢從一個帳戶轉移到另一個帳戶。 它是
同步
意味著只有一個線程可以訪問此方法,因為如果許多線程訪問它并在同一時間將資金從一個帳戶轉移到另一個帳戶,則余額會發生變化!
class Bank {private int[] accounts;Logger logger;public Bank(int accountNum, int baseAmount, Logger logger) {this.logger = logger;accounts = new int[accountNum];Arrays.fill(accounts, baseAmount);}public synchronized void transfer(int accountA, int accountB, int amount) {if (accounts[accountA] >= amount) {accounts[accountB] += amount;accounts[accountA] -= amount;logger.info("Transferred from account :" + accountA + " to account :" + accountB + " , amount :" + amount + " . balance :" + getBalance());}}
getBalance 始終返回總金額,并且每次轉賬后總金額應相同?
private synchronized int getBalance() {int balance = 0;for (int account : accounts) {balance += account;}return balance;}}
🔍類圖
🔍適用場景
監視器設計模式應該用于具有需要由多個線程或進程同時訪問和操作的共享資源的情況。 此模式在需要同步以防止競爭條件、數據損壞和不一致狀態的情況下特別有用。 以下是您應該考慮使用監視器模式的一些情況:
共享數據:當您的應用程序涉及需要由多個線程訪問和更新的共享數據結構、變量或資源時。 監視器確保一次只有一個線程可以訪問共享資源,從而防止沖突并確保數據一致性。
關鍵部分:當您有代碼的關鍵部分一次只需要由一個線程執行時。 關鍵部分是操作共享資源的代碼部分,并發訪問可能會導致問題。 監視器有助于確保在任何給定時間只有一個線程可以執行關鍵部分。
線程安全:當您需要確保線程安全而不是僅僅依賴鎖和信號量等低級同步機制時。 監視器提供了封裝同步和資源管理的更高級別的抽象。
等待和發信號:當您遇到線程需要等待滿足某些條件才能繼續操作時。 監視器通常包含線程等待特定條件以及其他線程在滿足條件時通知它們的機制。
死鎖預防:當您希望通過提供結構化方式來獲取和釋放共享資源上的鎖來防止死鎖時。 監視器通過確保資源訪問得到良好管理來幫助避免常見的死鎖情況。
并發數據結構:當您實現并發數據結構(例如隊列、堆棧或哈希表)時,多個線程需要操作該結構,同時保持其完整性。
資源共享:當多個線程需要共享有限的資源時,例如連接數據庫或訪問網絡套接字。 監視器可以幫助以受控方式管理這些資源的分配和釋放。
改進可維護性:當您想要將同步邏輯和共享資源管理封裝在單個對象中時,改進代碼組織并使并發相關代碼更容易推理。
🔍Ending
需要注意的是,監視器模式可能并不最適合所有并發場景。 在某些情況下,其他同步機制(例如鎖、信號量或并發數據結構)可能更合適。 此外,現代編程語言和框架通常提供更高級別的并發結構,抽象出低級別同步的復雜性。
在應用監視器模式之前,建議徹底分析應用程序的并發需求,并選擇最適合您需求的同步方法,同時考慮性能、復雜性和可用語言功能等因素。
希望本文能夠幫助讀者更深入地理解監視器模式,并在實際項目中發揮其優勢。謝謝閱讀!
希望這份博客草稿能夠幫助到你。如果有其他需要修改或添加的地方,請隨時告訴我。
?