思否出問題了,寫了一整天的文章,字字斟酌,段段構思,發佈的時候被吞了三分之二,我心態崩了,正在瘋狂碼字,下次再也不用內置編輯器碼字了。
零、前言
很久以前就接觸過觀察者模式,也寫過觀察者模式的文章,但以當時的水平尚不足以準確的理解這個設計模式,以至於文章寫的一片混亂。
這次再次嘗試從設計模式的初衷出發,結合計算機組成原理以及實際的應用來重新學習一邊觀察者模式,希望能糾正一些理解。
一、消息通知機制:同步和異步
無論是回調函數,還是觀察者模式,它們的初衷是為了異步,展開來説就是,為了解決併發導致的時間等待問題。
如果上面這句話不是很容易理解,我們先來舉個例子:
引例、IO方式
在早期的計算機中,當外設需要向主機發送數據時,數據會直接發送給CPU。
此時CPU每隔一段時間就要檢查外設的狀態,每當外設準備就緒後,就會傳輸一次數據,如此循環,直到數據全部傳輸完成。
在這段查詢——傳輸的循環中,一旦CPU啓動IO進程,就只能處理這一個任務,此時如果有多個併發任務,就會全部處於等待狀態,無法及時得到處理;
此外,CPU在不斷檢查外設狀態時,也會消耗大量的資源。
以上這種傳統的IO方式就稱為程序查詢方式,我們可以這樣理解:如果任務隊列中存在多個任務,比如:
由於CPU同一指令週期中,只能通過程序查詢方式執行IO或者進行運算,必須等待前面的工作結束後才能進行後面的工作,這種方式稱為同步。
後來人們認為這種方式效率太低,就發明了新的傳輸方式——DMA方式。
在這種方式中,CPU不再負責實際傳輸的過程,而是由一個叫做DMA控制器的設備負責實際傳輸,DMA控制器一端連接外設,一端連接主存,可以直接把數據從外設傳到主存中。
當傳輸完成後,DMA控制器會“通知”CPU(發起DMA中斷),來告訴CPU “數據已經收到,你可以開始處理了”,此時CPU才會對這部分數據進行運算。
需要注意的是,在DMA方式下,CPU已經不負責實際傳輸了,因此不再輪詢設備的狀態,也不會因為傳輸數據而佔用CPU週期,此時CPU真正解放出來,可以在IO的同時,並行的處理其他工作了。
當IO開始後,CPU不必再去管IO狀態,而是等待IO結束後再回來通知CPU,這種方式稱為異步。
通過這個IO的例子,我們不難發現:異步是為了解決等待的問題。
同步和異步
同步:發起請求後,必須等待結果返回後才能執行後面的操作。
異步:發起請求後不必等待結果,由另一個線程去執行請求,執行結束後,通知主要線程。
二、觀察者模式
也許前面的例子並不是很恰當,但如果看懂了上面的例子就不難發現,底層硬件和軟件開發的邏輯有相通之處,在軟件中,我們也要經常處理一些“變化”的問題,當對象數據變化後,如果及時通知其他對象更新數據呢?
請看例子:
報社的故事
有一個報社,可以向所有訪問它的讀報者提供報紙,但每一次報紙更新時間都是不確定的,讀報者有若干人,如何才能保證所有的讀報者都能在第一時間收到報紙更新呢?
有一個笨方法,讀報者每天去報社問一次。但問題在於,這樣只能獲得24小時內的更新,而不是立即獲得更新;
如果想加速獲取更新,只能加快訪問的頻率,最終變成了讀報人緊緊的盯着報社,等着報紙的更新,但這樣讀報人就沒有辦法做其他的事情了。
後來讀報人有了新的辦法:
他們向報社留下了聯繫方式,告訴報社,只要有了新的報紙,就第一時間通知讀報人。有的讀報人留下了一個通知模板