進程線程、同步異步、阻塞非阻塞、併發並行詳解

基本概念

1 進程和線程

進程(Process):

是Windows系統中的一個基本概念,它包含着一個運行程序所需要的資源。一個正在運行的應用程序在操作系統中被視爲一個進程,進程可以包括一個或多個線程。

線程是操作系統分配處理器時間的基本單元,在進程中可以有多個線程同時執行代碼。進程之間是相對獨立的,一個進程無法訪問另一個進程的數據(除非利用分佈式計算方式),一個進程運行的失敗也不會影響其他進程的運行,Windows系統就是利用進程把工作劃分爲多個獨立的區域的。進程可以理解爲一個程序的基本邊界。是應用程序的一個運行例程,是應用程序的一次動態執行過程。

線程(Thread):

是進程中的基本執行單元,是操作系統分配CPU時間的基本單位,一個進程可以包含若干個線程,在進程入口執行的第一個線程被視爲這個進程的主線程。線程主要是由CPU寄存器、調用棧和線程本地存儲器(Thread Local Storage,TLS)組成的。CPU寄存器主要記錄當前所執行線程的狀態,調用棧主要用於維護線程所調用到的內存與數據,TLS主要用於存放線程的狀態信息。

進程和線程的區別

進程和線程的主要差別在於它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。

線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的併發操作,只能用線程,不能用進程。

  • 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程。

  • 線程的劃分尺度小於進程,使得多線程程序的併發性高。

  • 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。

  • 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。

  • 從邏輯角度來看,多線程的意義在於一個應用程序中,有多個執行部分可以同時執行。但操作系統並沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。

2 同步(Sync)和異步(Async)

同步:

所謂同步,就是發出一個功能調用時,在沒有得到結果之前,該調用就不返回或繼續執行後續操作。

簡單來說,同步就是必須一件一件事做,等前一件做完了才能做下一件事。

例如:B/S模式中的表單提交,具體過程是:客戶端提交請求->等待服務器處理->處理完畢返回,在這個過程中客戶端(瀏覽器)不能做其他事。

異步:

異步與同步相對,當一個異步過程調用發出後,調用者在沒有得到結果之前,就可以繼續執行後續操作。當這個調用完成後,一般通過狀態、通知和回調來通知調用者。對於異步調用,調用的返回並不受調用者控制。

對於通知調用者的三種方式,具體如下:

  • 狀態:即監聽被調用者的狀態(輪詢),調用者需要每隔一定時間檢查一次,效率會很低。

  • 通知:當被調用者執行完成後,發出通知告知調用者,無需消耗太多性能。

  • 回調:與通知類似,當被調用者執行完成後,會調用調用者提供的回調函數。

例如:B/S模式中的ajax請求,具體過程是:客戶端發出ajax請求->服務端處理->處理完畢執行客戶端回調,在客戶端(瀏覽器)發出請求後,仍然可以做其他的事。

同步和異步的區別:

總結來說,同步和異步的區別:請求發出後,是否需要等待結果,才能繼續執行其他操作。

3 阻塞和非阻塞

阻塞和非阻塞這兩個概念與程序(線程)等待消息通知(無所謂同步或者異步)時的狀態有關。也就是說阻塞與非阻塞主要是程序(線程)等待消息通知時的狀態角度來說的。

阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態。

阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之後纔會返回。

非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。

4 併發並行

併發:在操作系統中,是指一個時間段中有幾個程序都處於已啓動運行到運行完畢之間,且這幾個程序都是在同一個處理機上運行,但任一個時刻點上只有一個程序在處理機上運行。

當有多個線程在操作時,如果系統只有一個CPU,則它根本不可能真正同時進行一個以上的線程,它只能把CPU運行時間劃分成若干個時間段,再將時間 段分配給各個線程執行,在一個時間段的線程代碼運行時,其它線程處於掛起狀。。這種方式我們稱之爲併發(Concurrent)。

並行:當系統有一個以上CPU時,則線程的操作有可能非併發。當一個CPU執行一個線程時,另一個CPU可以執行另一個線程,兩個線程互不搶佔CPU資源,可以同時進行,這種方式我們稱之爲並行(Parallel)

併發和並行的區別:

  • 你吃飯吃到一半,電話來了,你一直到吃完了以後纔去接,這就說明你不支持併發也不支持並行。

  • 你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支持併發。

  • 你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支持並行。

併發的關鍵是你有處理多個任務的能力,不一定要同時。並行的關鍵是你有同時處理多個任務的能力。

所以我認爲它們最關鍵的點就是:是否是『同時』。

二 異步和多線程區別?(原理篇)

1 異步和多線程有什麼區別?

其實,異步是目的,而多線程是實現這個目的的方法。異步是說,A發起一個操作後(一般都是比較耗時的操作,如果不耗時的操作就沒有必要異步了),可以繼續自顧自的處理它自己的事兒,不用幹等着這個耗時操作返回。

2 多線程和異步操作的異同

多線程和異步操作兩者都可以達到避免調用線程阻塞的目的,從而提高軟件的可響應性。甚至有些時候我們就認爲多線程和異步操作是等同的概念。但是,多線程和異步操作還是有一些區別的。而這些區別造成了使用多線程和異步操作的時機的區別。

3 異步操作的本質

所有的程序最終都會由計算機硬件來執行,所以爲了更好的理解異步操作的本質,我們有必要了解一下它的硬件基礎。熟悉電腦硬件的朋友肯定對DMA這個詞不陌生,硬盤、光驅的技術規格中都有明確DMA的模式指標,其實網卡、聲卡、顯卡也是有DMA功能的。

DMA就是直 接內存訪問的意思,也就是說,擁有DMA功能的硬件在和內存進行數據交換的時候可以不消耗CPU資源。只要CPU在發起數據傳輸時發送一個指令,硬件就開 始自己和內存交換數據,在傳輸完成之後硬件會觸發一箇中斷來通知操作完成。這些無須消耗CPU時間的I/O操作正是異步操作的硬件基礎。所以即使在DOS 這樣的單進程(而且無線程概念)系統中也同樣可以發起異步的DMA操作。

4 線程的本質

線程不是一個計算機硬件的功能,而是操作系統提供的一種邏輯功能,線程本質上是進程中一段併發運行的代碼,所以線程需要操作系統投入CPU資源來運行和調度。

5 異步操作的優缺點

因爲異步操作無須額外的線程負擔,並且使用回調的方式進行處理,在設計良好的情況下,處理函數可以不必使用共享變量(即使無法完全不用,最起碼可以減少 共享變量的數量),減少了死鎖的可能。當然異步操作也並非完美無暇。編寫異步操作的複雜程度較高,程序主要使用回調方式進行處理,與普通人的思維方式有些 出入,而且難以調試。

6 多線程的優缺點

多線程的優點很明顯,線程中的處理程序依然是順序執行,符合普通人的思維習慣,所以編程簡單。但是多線程的缺點也同樣明顯,線程的使用(濫用)會給系統帶來上下文切換的額外負擔。並且線程間的共享變量可能造成死鎖的出現。

異步與多線程,從辯證關係上來看,異步和多線程並不是一個同等關係,異步是目的,多線程只是我們實現異步的一個手段。什麼是異步:異步是當一個調用請求發送給被調用者,而調用者不用等待其結果的返回。實現異步可以採用多線程技術或則交給另外的進程來處理。擴展:多線程基礎體系知識清單

三 異步,多線程和並行的區別?(故事篇)

非專業人員,就用非專業的語言解釋下吧,比喻不夠貼切,但大概是那麼個意思,

先聽我講一個故事:

那還是10年前,還沒有12306的年代,大家買票只能去火車站買。因爲大家都要過年回家,都還不想等,火車站只有一個,窗口只有那麼多,頭疼啊。更頭疼的是,排到窗口的那個人,各種挑剔,不要貴的,不要晚上的,不要站票……跟售票員各種墨跡,後面的人更加着急,一個個義憤填膺,罵爹罵娘。

現在假設整個城市就只有1個火車,1個售票員,每個乘客諮詢售票員後需要思考1分鐘再決定買哪趟車的票。

1。異步:在買票的人諮詢後,需要思考1分鐘,馬上靠邊站,但不用重新排隊,什麼時候想清楚可以立馬去跟售票員去買票。在該人站在旁邊思考的時候,後面的人趕緊上去接着買。這時候隊伍是很快的挪動的,沒有阻塞,售票員的最大化的效率。

2。多線程:火車站開n個窗口(但還是隻有一個人售票),外面同時排n個隊,售票員回答諮詢者問題後,立馬馬上去下個窗口,然後繼續輪換到下個窗口…..哪個窗口的人決定好了,售票員立馬過去買給他。這個時候乘客比較簡單,但萬一那個隊伍有人思考半天糾結,後面的人就悲劇了。

3。並行:複製n個火車站,同時賣票,買票能力大大增強。大家也可以哪個火車站人少,就去那個買票。

可見:在只有一個火車站,且只有一個售票員的情況下,賣完一個再賣一個就會導致資源浪費,效率低下,隊伍卡死,很難往前挪動。1,2優化的辦法都解決了隊伍不動,售票率低下的問題。但增加火車站,增加窗口,增加售票員纔是好辦法。擴展:多線程基礎體系知識清單

結論:

1。異步和多線程其實效率差不多,但是開的窗口不多例如3個,同時有很多人都是去花5分鐘,而不是1分鐘去糾結的時候,多線程效率實際是低於異步的,因爲售票員還是常遇到3個隊伍同時卡在那糾結不能買票的時候。

2。這2個概念拿來對比也有點不合適,因爲他們不是一個概念,多線程的目的還是爲了實現異步,多線程應該是一種實現異步的手段。異步應該去跟同步比較纔對。

3。多線程比較簡單,但需要增設窗口,增加成本,且售票員比較累這類似apache下php,和node。js下javascript的關係,一個是多線程,但是是阻塞的,另外一個是單線程異步非阻塞的。php的方案比較符合常規思維,但比較費內存,node。js非阻塞,用較少的資源就能完成同樣的任務,但編程比較費神。

4。並行,類似同時利用多核cpu的各個核去計算。併發可分爲僞併發、真併發。前者例如單核處理器的併發,後者發是指多核處理器的併發。

5。終極辦法是並行計算,並且每個cpu下進行異步計算,這樣你的每個核都充分利用。只不過對編程要求太高了太高了,如果不是密集型計算,例如大型有限元計算(多采用併發),或者服務器同時處理上千的訪問(多采用異步或者多線程),還是老老實實的用傳統的辦法吧,畢竟常規程序的計算量對現在的硬件來說,問題都不大。擴展:多線程基礎體系知識清單

四 阻塞非阻塞與同步異步的區別?(故事篇)

理解同步阻塞、同步非阻塞、異步阻塞、異步阻塞、異步非阻塞

同步/異步關注的是消息通知的機制,而阻塞/非阻塞關注的是程序(線程)等待消息通知時的狀態。

以小明下載文件打個比方,從這兩個關注點來再次說明這兩組概念,希望能夠更好的促進大家的理解。

同步阻塞:小明一直盯着下載進度條,到 100% 的時候就完成。

  • 同步體現在:等待下載完成通知;

  • 阻塞體現在:等待下載完成通知過程中,不能做其他任務處理;

同步非阻塞:小明提交下載任務後就去幹別的,每過一段時間就去瞄一眼進度條,看到 100% 就完成。

  • 同步體現在:等待下載完成通知,但是要在;

  • 非阻塞體現在:等待下載完成通知過程中,去幹別的任務了,只是時不時會瞄一眼進度條;【小明必須要在兩個任務間切換,關注下載進度】

異步阻塞:小明換了個有下載完成通知功能的軟件,下載完成就“叮”一聲。不過小明仍然一直等待“叮”的聲音(看起來很傻,不是嗎)。

  • 異步體現在:下載完成“叮”一聲通知;

  • 阻塞體現在:等待下載完成“叮”一聲通知過程中,不能做其他任務處理;

異步非阻塞:仍然是那個會“叮”一聲的下載軟件,小明提交下載任務後就去幹別的,聽到“叮”的一聲就知道完成了。

  • 異步體現在:下載完成“叮”一聲通知;

  • 非阻塞體現在:等待下載完成“叮”一聲通知過程中,去幹別的任務了,只需要接收“叮”聲通知即可;【軟件處理下載任務,小明處理其他任務,不需關注進度,只需接收軟件“叮”聲通知,即可】

也就是說,同步/異步是“下載完成消息”通知的方式(機制),而阻塞/非阻塞則是在等待“下載完成消息”通知過程中的狀態(能不能幹其他任務),在不同的場景下,同步/異步、阻塞/非阻塞的四種組合都有應用。

所以,綜上所述,同步和異步僅僅是關注的消息如何通知的機制,而阻塞與非阻塞關注的是等待消息通知時的狀態。也就是說,同步的情況下,是由處理消息者自己去等待消息是否被觸發,而異步的情況下是由觸發機制來通知處理消息者,所以在異步機制中,處理消息者和觸發機制之間就需要一個連接的橋樑:

在小明的例子中,這個橋樑就是軟件“叮”的聲音。

同步/異步與阻塞/非阻塞

1 同步阻塞形式

效率是最低的,

拿上面的例子來說,就是你專心等待下載完成,什麼別的事都不做。

實際程序中:就是未對fd 設置O_NONBLOCK標誌位的read/write 操作;

2 異步阻塞形式

異步操作是可以被阻塞住的,只不過它不是在處理消息時阻塞,而是在等待消息通知時被阻塞。

比如select 函數,假如傳入的最後一個timeout參數爲NULL,那麼如果所關注的事件沒有一個被觸發,程序就會一直阻塞在這個select 調用處。

3 同步非阻塞形式

實際上是效率低下的,

想象一下你一邊幹別的事情一邊還需要擡頭看下載完成沒有,如果把幹別的事情和觀察下載完成情況的位置看成是程序的兩個操作的話,這個程序需要在這兩種不同的行爲之間來回的切換,效率可想而知是低下的。

很多人會寫阻塞的read/write 操作,但是別忘了可以對fd設置O_NONBLOCK 標誌位,這樣就可以將同步操作變成非阻塞的了。

4 異步非阻塞形式

效率更高,

因爲等待下載完成是你(等待者)的事情,而通知你則是電腦(消息觸發機制)的事情,程序沒有在兩種不同的操作中來回切換。

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