非同步/同步,阻塞/非阻塞,單執行緒/多執行緒概念梳理

fairjm發表於2019-02-25

本文來自 fairjm@圖靈社群 轉截請註明出處


最近看了一文說到非同步是單執行緒的,頓時就傻眼了,對相關概念和同事進行了一些討論和總結.
文中的描述是以我的理解來說的,可能不一定準確甚至正確,有錯歡迎指正.

這三個概念我認為是描述不同的維度的,概念正交.

非同步 同步

非同步和同步是不同的流程設計風格.
但存在依賴關係的操作之間是同步的,也就是如果操作B依賴操作A的返回,那麼B必須要在A結束後才能執行.
比如你要讀取檔案然後對檔案內容進行處理,那麼讀取內容和處理內容就是同步的.

而非同步這是操作間沒有依賴關係,或者先後順序並不重要.
比如使用者登陸要給登陸獎勵,在確認使用者可登陸後之後的登陸流程和發放獎勵間並無依賴關係,那麼他們就可以非同步執行.

這個概念主要描述依賴關係和流程設計.

阻塞 非阻塞

這個概念是描述操作是否會立即返回的.
這個概念常常和非同步/同步混在一起.
同步就一定是阻塞的嗎,這不一定,這取決於同步執行裡的各個操作是否是阻塞的.

非阻塞操作可以被用在非同步API的實現.
基於單執行緒的非同步API實現裡的操作一般都會要求為非阻塞.

單執行緒 多執行緒

這兩個概念常和非同步 同步混在一起.
比如認為非同步一定是要多執行緒才能實現的,但其實不然,有很多基於Eventloop的單執行緒實現.
單執行緒 多執行緒主要描述的是執行的環境.
如圖:
enter image description here
(來源參考3)

一些實現中相關的概念

在實現中,為了高效的執行這些概念會被組合起來使用.
單執行緒的非同步操作,需要依賴非阻塞操作(不然單個執行緒就直接阻塞了).而這裡非同步的目的是為了提高執行緒的利用率,這在IO密集的應用中比較有效.
但如果操作本身是計算密集的,那麼單執行緒的非同步操作就沒有太大的意義了.

而如果無法滿足操作都是非阻塞的,那常常會使用多執行緒來規避主執行緒(例如伺服器中的請求處理執行緒和GUI中的UI執行緒)阻塞.
這種一般會返回Future等類似的佔位符,並提供非阻塞查詢結果是否返回,或者支援回撥函式.
這在java中比較常見,畢竟java世界中的阻塞操作比較多.

上述概念和IO的關係.
一些對應的API.
enter image description here
這些操作和單執行緒/多執行緒沒什麼關係.
更多的內容之前有翻譯一篇文章: 各個型別的IO - 阻塞, 非阻塞,多路複用和非同步
對應語言的各種IO要看使用了系統提供的哪些型別的API.
例如Java,在Linux中的AIO是多執行緒模擬實現的,而在windows下使用了IOCP使用.

參考資料:
1.https://blog.slaks.net/2014-12-23/parallelism-async-threading-explained/

2.https://stackoverflow.com/questions/41770985/i-o-blocking-in-green-threads

3.https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean

相關文章