併發與並行,同步與異步阻塞

併發與並行


  • 併發:指的是任務數多餘cpu核數,通過操作系統的各種任務調度算法,
    實現用多個任務“一起”執行(實際上總有一些任務不在執行,因爲切換任務的速度相當快,
    看上去一起執行而已),一個 CPU 執行多個任務.
  • 並行:指的是任務數小於等於cpu核數,即任務真的是一起執行的。多個 CPU 執行多個任務(一個 CPU 負責一個任務)
    可以這樣理解:

你吃飯吃到一半,電話來了,你一直到吃完了以後纔去接,這就說明你不支持併發也不支持並行。
你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支持併發。
你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支持並行。
併發的關鍵是你有處理多個任務的能力,不一定要同時。
並行的關鍵是你有同時處理多個任務的能力。
所以我認爲它們最關鍵的點就是:是否是『同時』。

同步與異步阻塞

老張愛喝茶,廢話不說,煮開水。
出場人物:老張,水壺兩把(普通水壺,簡稱水壺;會響的水壺,簡稱響水壺)。
1 老張把水壺放到火上,立等水開。(同步阻塞)
老張覺得自己有點傻
2 老張把水壺放到火上,去客廳看電視,時不時去廚房看看水開沒有。(同步非阻塞)
老張還是覺得自己有點傻,於是變高端了,買了把會響笛的那種水壺。水開之後,能大聲發出嘀~~~~的噪音。
3 老張把響水壺放到火上,立等水開。(異步阻塞)
老張覺得這樣傻等意義不大
4 老張把響水壺放到火上,去客廳看電視,水壺響之前不再去看它了,響了再去拿壺。(異步非阻塞)
老張覺得自己聰明瞭。
所謂同步異步,只是對於水壺而言。
普通水壺,同步;響水壺,異步。
雖然都能幹活,但響水壺可以在自己完工之後,提示老張水開了。這是普通水壺所不能及的。
同步只能讓調用者去輪詢自己(情況2中),造成老張效率的低下。
所謂阻塞非阻塞,僅僅對於老張而言。
立等的老張,阻塞;看電視的老張,非阻塞。
情況1和情況3中老張就是阻塞的,媳婦喊他都不知道。雖然3中響水壺是異步的,可對於立等的老張沒有太大的意義。所以一般異步是配合非阻塞使用的,這樣才能發揮異步的效用。

python 中的同步與異步
當提到同步與異步,大家不免會想到另一組詞語:阻塞與非阻塞。通常,同時提到這個這幾個詞語一般實在討論 network io 的時候,在《unix network programming》中有詳盡的解釋,網絡中也有許多講解生動的文章。
  本文所討論的同步與異步,是指對於請求的發起者,是否需要等到請求的結果(同步),還是說請求完畢的時候以某種方式通知請求發起者(異步)。在這個語義環境下,阻塞與非阻塞,是指請求的受理者在處理某個請求的狀態,如果在處理這個請求的時候不能做其它事情(請求處理時間不確定),那麼稱之爲阻塞,否則爲非阻塞。
  舉個例子,我去櫃檯辦理業務,那我是請求者,櫃員時受理者。如果我在櫃檯一直等着櫃員辦理,直到辦理完畢,那麼對於我來說,就是同步的;如果我只是在櫃員那裏登記,然後到一邊歇着,等櫃員辦理完畢之後告訴我結果,那麼就是異步的。對於櫃員,辦理業務的時候可能需要等待打印機打印,如果在這個時候櫃員去處理其他人的業務,那麼就是非阻塞的,如果一定得到把我的業務辦完再接待下一位顧客,那麼就是阻塞的。

  本文站在請求發起者的角度來思考同步與異步,在實際開發中,一個最簡單的例子就是 http 請求。假設這麼一個場景,程序需要訪問兩個網址(通過 url),如果只有一個線程。那麼同步與異步分別怎麼處理呢

python 的 urllib 是同步的,即當一個請求結束之後才能發起下一個請求,我們知道 http 請求基於 tcp,tcp 又需要三次握手建立連接(https 的握手會更加複雜),在這個過程中,程序很多時候都在等待IO,CPU 空閒,但是又不能做其他事情。但同步模式的優點是比較直觀,符合人類的思維習慣: 那就是一件一件的來,幹完一件事再開始下一件事。在同步模式下,要想發揮多核 CPU 的威力,可以使用多進程或者多線程(注意 python 的多線程並不能發揮多核,嚴格意義上是單線程)。

如果發出了請求就立即返回,這個時候程序可以做其他事情,等請求完成了時候通過某種方式告知結果,然後請求者再繼續再來處理請求結果,那麼我們稱之爲異步,最常見的就是回調(callback),在 python 中,tornado 提供了異步的 http 請求。

異步的優勢所在:不用在 IO 上等待,在單核 CPU 上就有更好的性能。

以上部分觀點引自知乎,侵刪。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章