好久沒上線了,今天記錄編程中老掉牙的幾個關鍵術語,一個言簡意賅的術語定義包含主謂賓定狀補, 我們應從貌似雷同的術語中體會到不同術語的表象行爲、側重點。
下面給出的3對技術術語,都是很核心、易混淆的概念點,但是多少還是有些表象、側重點的不同。
書讀百遍其義自見, 請關注最下方給出的微軟官方技術文獻, 自勉!!
1. 同步/異步、 阻塞/非阻塞
阻塞操作不等於同步,非阻塞操作也不等於異步。實際上,它們之間並沒有直接的聯繫。
先說同步,這個很簡單,就是按照代碼來順序執行。
比如下面這段僞代碼:
local res, err = query-mysql(sql)
local value, err = query-redis(key)
在同一請求連接中,如果要等 MySQL 的查詢結果返回後,才能繼續去查詢 Redis,那就是同步;
如果不用等 MySQL 的返回,就能繼續往下走,去查詢 Redis,那就是異步。
完全不care MYSQL的查詢結果,也不是業務想要的,一般的實踐是query-mysql函數快速返回一個
awaitable對象
,通過狀態查詢、事件通知的方式拿到異步行爲的結果。
再來說說非阻塞,這是一個很容易和“異步”混淆的概念。
這裏我們說的“阻塞”,特指阻塞操作系統線程。
我們繼續看上面的例子,假設查詢 MySQL 需要1s 的時間,如果在這1s 內,操作系統的資源(CPU)是空閒着並傻傻地等待返回,那就是阻塞;
如果 CPU 趁機去處理其他連接的請求,那就是非阻塞。
總體而言:
同步/異步雖然表現爲函數調用,實際宏觀上描述了一信息對齊方式, 異步調用,異步通信,異步任務均表現爲發出通信動作後即刻返回,通過狀態通知、回調函數來拿到通信結果。
阻塞/非阻塞關注的是應用程序在等待數據返回的狀態問題:在得到結果之前,cpu若傻傻等待是阻塞(被掛起)。
- 基於任務的異步模式 (TAP), 主流推薦
- 基於事件的異步模式 (EAP), 過時不推薦
- 異步編程模型 (APM) 模式(也稱爲 IAsyncResult 模式), 過時不推薦
2,3已經不被推薦(2,3其實很貼近異步的行爲認知),目前主流推薦的TAP async/await語法糖,以同步姿勢簡化了異步編程, 但是語法糖也讓我們不容易理解異步的本質: async/await語法糖具備傳染性,導致async/await在整個代碼結構氾濫使用,在被傳染的async/await層級, 根本不體現通信交互,弱化了開發者對於最底層是異步通信的認知。
微軟喜歡搞拖拽控件、語法糖給到開發者,讓我們沉迷於便利的開發體驗,忽視了樸素的核心本質。
2. 事件/消息
事件是對條件或狀態更改的輕量級通知。
- 事件的發佈者對如何處理事件沒有期望。
- 事件的使用者決定如何處理通知。
- 事件報告狀態變化並且是可操作的, 要進行下一步,消費者只需要知道發生了什麼。事件數據包含關於發生了什麼事情的信息,但不包含觸發事件的數據。例如,事件通知使用者文件已創建。它可能有關於文件的一般信息,但它沒有文件本身。
- 事件可以是離散的單位,也可以是一系列事件的一部分。
一系列事件報告了一種狀況,並且是可分析的。這些事件是按時間順序排列並相互關聯的。消費者可通過序列事件來分析發生了什麼。
消息是由服務生成的原始數據,將在其他地方使用或存儲 。
- 消息包含觸發消息管道的數據。
- 消息的發佈者對於消費者如何處理消息有一個期望。雙方之間存在一份契約。
例如,發佈者發送帶有原始數據的消息,並期望消費者從該數據創建文件,並在工作完成時發送響應。
3. 委託/事件
委託更像一個類的一個屬性,只不過屬性值是函數,公開的委託可以像類屬性一樣,自由賦值。
在衆多語言中,委託與閉包密切相關。
和委託類似,事件也是後期綁定機制。 實際上,事件是建立在對委託的語言支持之上。
In the .NET class library, events are based on the EventHandler delegate and the EventArgs base class.
public delegate void EventHandler(object? sender, EventArgs e);
後期綁定機制: 組件通過調用可在運行時識別的方法進行通信。 它們都支持單個和多個訂閱服務器方法。 這稱爲單播和多播支持。
兩者均支持用於添加和刪除處理程序的類似語法,引發事件和調用委託也是相同的調用語法。 它們甚至都支持與 ?. 運算符結合的 Invoke() 語法。
使用委託還是事件有一些考量:
事件是對條件或狀態更改的輕量級通知。事件有可能被提前預置了反饋,也可能根本沒預置反饋。
(1). 若偵聽器可選,更傾向事件
A組件引發了事件,也許並不引發其他組件的連鎖反應,也就是沒有預置偵聽器,這種雖然用委託也行,但是更傾向對事件賦值偵聽器。
(2). 事件只能由定義事件的組件自行觸發 ,而不能由外部觸發。
包含事件的類以外的類只能添加和刪除事件偵聽器;只有包含事件的類才能引發事件。
還是那句話,事件更強調組件在滿足條件或自身狀態變更時觸發。
(3). 事件不care偵聽器的返回值
與(1)相關,因爲事件的引發者本身也不care有沒有偵聽器。
結語
搬磚多年,越來越體會到精準理解術語的重要性,一個言簡意賅的術語定義 包含主謂賓定狀補, 我們應從貌似雷同的術語中體會到不同術語的表象行爲、側重點。
上面三對概念:冥冥中存在某種微妙聯繫。
同步/異步: 描述了信息的對齊方式,如果是異步會即時返回,使用狀態通知、回調事件來獲得操作結果。
事件/消息:描述了信息的側重點, 事件強調了某組件在滿足某種條件、時間點而觸發了某次行爲,不care是否有消費方對這個行爲產生了連鎖反應。
消息是生產方要傳遞的原始數據,消息生產方對消息被消費是有期待的(存在消息格式便於消費方理解)。
委託/事件: 更接近於事件的技術實現,事件是基於委託實現的,事件更強調內生引發、委託可認爲是類屬性。