當前位置:
首頁 >
同步与异步以及线程与进程
發布時間:2025/3/15
25
豆豆
生活随笔
收集整理的這篇文章主要介紹了
同步与异步以及线程与进程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
寫過爬蟲的都知道,爬蟲的性能瓶頸在于IO,因為爬蟲是一個IO密集型業務,程序需要發起網絡請求,必然就有IO阻塞,
通常請求一個URL耗時要幾百毫秒到幾秒不等,而我們的CPU處理速度驚人,兩者的速度就好比烏龜跟火箭的差別。
在單線程同步阻塞程序中,如果要獲取一個網站所有的URL,假設100個URL,平均每個URL請求的時間是1秒,
那么在單線程同步場景下,最快也需要100秒鐘,才能把所有的頁面爬取下來。
于是,我們想到了更好的一種辦法就是采用多線程或者多進程,但是由于在Python中臭名昭著的GIL,導致做不到真正的并行運算,
在同一時間內,就算有多核CPU,也無法被利用起來,這樣雖然能做到并發,但是沒法并行,在單個CPU里切換線程,還有切換成本,以及線程的創造成本。
如果使用多進程,雖然能利用多核處理的優勢,但是多進程的創建成本比線程更高,而IO密集型任務,CPU不是瓶頸。
所以,后來Python引入了異步編程,異步編程使得CPU不再需要再去等待耗時的操作,而是讓出CPU時間給其他任務執行,
熟悉電腦硬件的朋友肯定對DMA這個詞不陌生,硬盤、光驅的技術規格中都有明確DMA的模式指標,其實網卡、聲卡、顯卡也是有DMA功能的。
DMA就是直接內存訪問的意思,也就是說,擁有DMA功能的硬件在和內存進行數據交換的時候可以不消耗CPU資源。
只要CPU在發起數據傳輸時發送一個指令,硬件就開始自己和內存交換數據,在傳輸完成之后硬件會觸發一個中斷來通知操作完成。
這些無須消耗CPU時間的I/O操作正是異步操作的硬件基礎。所以即使在DOS這樣的單進程(而且無線程概念)系統中也同樣可以發起異步的DMA操作。
而異步則是相反,*調用*在發出之后,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出后,調用者不會立刻得到結果。
而是在*調用*發出后,*被調用者*通過狀態、通知來通知調用者,或通過回調函數處理這個調用。典型的異步編程模型比如Node.js
舉個通俗的例子:
你打電話問書店老板有沒有《分布式系統》這本書,如果是同步通信機制,書店老板會說,你稍等,”我查一下",然后開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而異步通信機制,書店老板直接告訴你我查一下啊,查好了打電話給你,然后直接掛電話了(不返回結果)。然后查好了,他會主動打電話給你。在這里老板通過“回電”這種方式來回調。
阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之后才會返回。
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。
還是上面的例子,
你打電話問書店老板有沒有《分布式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,
如果是非阻塞式調用,你不管老板有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老板有沒有返回結果。
在這里阻塞與非阻塞與是否同步異步無關。跟老板通過什么方式回答你結果無關。
進程:具有一定獨立功能的程序關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
線程:進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。
線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),
但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
2.關系
一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以并發執行.
相對進程而言,線程是一個更加接近于執行體的概念,它可以與同進程中的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
3.區別
進程和線程的主要差別在于它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響。
而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,
所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。
但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
1) 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.
2) 線程的劃分尺度小于進程,使得多線程程序的并發性高。
3) 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
4) 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。
? ?但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
5) 從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。
? ?但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
4.優缺點
線程和進程在使用上各有優缺點:
線程執行開銷小,但不利于資源的管理和保護;而進程正相反。
Why:?
由于CPU與其他PC資源之間速度的不協調,人們想提高資源利用率,所以人們提出了多任務系統。
得益于CPU的計算速度,我們可以“同時”運行多個任務,實質上是多個任務之間輪流使用CPU資源,由于速度超快,給用戶的感覺就是連續的。
How:?
1)任務的執行需要依賴各個PC資源,我們可以稱為計算機執行的上下文環境。
? ?要實現“同時執行”,就需要不斷輪換,為了后來繼續從當前狀態執行下去,計算機需要保存切換前的程序上下文。
? ?所以有了進程:用進程去描述程序當前上下文的狀態信息----內存位置、變量值、任務ID……所以,進程是資源分配的單位。
? ?一般來說宏觀上可以看做是一個軟件的運行,例如一個word文檔的打開。
2)多個任務之間切換因為要保存上下文、調入上下文,一旦多了的時候,還是有一定的時間消耗的。
? ?為了進一步提高資源利用率,人們在進程中,引入了線程,線程只是CPU輪流調度的單位,其他上下文信息用所在進程中的。
? ?這樣上下文切換的耗時就降了下來。同樣的,宏觀上來可以看做是一個軟件中的多個處理功能,例如上述打開word中拼寫檢查功能、字體加粗……
So, What:?
一般來說,進程是資源的分配單位,線程是CPU在進程內切換的單位,線程屬于進程。所以運行某個軟件,相當于開了一個進程。
在這個軟件運行的過程里(在這個進程里),多個工作支撐的完成QQ的運行,那么這“多個工作”分別有一個線程。
再打一個通俗易懂的比方吧!
比如你去一個食堂吃飯。里面有A,B,C,D等一些窗口可以打飯菜或者米粉麻辣燙什么的。
但是每一個窗口又有打這些菜的師傅。
那么這些窗口就是進程。
那個那些窗口里面打菜的師傅就是線程。
這個食堂就是系統了,系統去分配這些進程。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
通常請求一個URL耗時要幾百毫秒到幾秒不等,而我們的CPU處理速度驚人,兩者的速度就好比烏龜跟火箭的差別。
在單線程同步阻塞程序中,如果要獲取一個網站所有的URL,假設100個URL,平均每個URL請求的時間是1秒,
那么在單線程同步場景下,最快也需要100秒鐘,才能把所有的頁面爬取下來。
于是,我們想到了更好的一種辦法就是采用多線程或者多進程,但是由于在Python中臭名昭著的GIL,導致做不到真正的并行運算,
在同一時間內,就算有多核CPU,也無法被利用起來,這樣雖然能做到并發,但是沒法并行,在單個CPU里切換線程,還有切換成本,以及線程的創造成本。
如果使用多進程,雖然能利用多核處理的優勢,但是多進程的創建成本比線程更高,而IO密集型任務,CPU不是瓶頸。
所以,后來Python引入了異步編程,異步編程使得CPU不再需要再去等待耗時的操作,而是讓出CPU時間給其他任務執行,
這樣假如有100個任務,每個任務是1秒鐘,就可以做到理論上只需要1秒鐘就可以完成所有的任務。
同步與異步
異步操作的本質
所有的程序最終都會由計算機硬件來執行,所以為了更好的理解異步操作的本質,我們有必要了解一下它的硬件基礎。?熟悉電腦硬件的朋友肯定對DMA這個詞不陌生,硬盤、光驅的技術規格中都有明確DMA的模式指標,其實網卡、聲卡、顯卡也是有DMA功能的。
DMA就是直接內存訪問的意思,也就是說,擁有DMA功能的硬件在和內存進行數據交換的時候可以不消耗CPU資源。
只要CPU在發起數據傳輸時發送一個指令,硬件就開始自己和內存交換數據,在傳輸完成之后硬件會觸發一個中斷來通知操作完成。
這些無須消耗CPU時間的I/O操作正是異步操作的硬件基礎。所以即使在DOS這樣的單進程(而且無線程概念)系統中也同樣可以發起異步的DMA操作。
同步和異步關注的是消息通信機制 (synchronous communication/ asynchronous communication)
所謂同步,就是在發出一個*調用*時,在沒有得到結果之前,該*調用*就不返回。但是一旦調用返回,就得到返回值了。換句話說,就是由*調用者*主動等待這個*調用*的結果。而異步則是相反,*調用*在發出之后,這個調用就直接返回了,所以沒有返回結果。換句話說,當一個異步過程調用發出后,調用者不會立刻得到結果。
而是在*調用*發出后,*被調用者*通過狀態、通知來通知調用者,或通過回調函數處理這個調用。典型的異步編程模型比如Node.js
舉個通俗的例子:
你打電話問書店老板有沒有《分布式系統》這本書,如果是同步通信機制,書店老板會說,你稍等,”我查一下",然后開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而異步通信機制,書店老板直接告訴你我查一下啊,查好了打電話給你,然后直接掛電話了(不返回結果)。然后查好了,他會主動打電話給你。在這里老板通過“回電”這種方式來回調。
阻塞與非阻塞
阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態。阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之后才會返回。
非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。
還是上面的例子,
你打電話問書店老板有沒有《分布式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果,
如果是非阻塞式調用,你不管老板有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老板有沒有返回結果。
在這里阻塞與非阻塞與是否同步異步無關。跟老板通過什么方式回答你結果無關。
進程和線程的區別
1.定義進程:具有一定獨立功能的程序關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位.
線程:進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。
線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),
但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源.
2.關系
一個線程可以創建和撤銷另一個線程;同一個進程中的多個線程之間可以并發執行.
相對進程而言,線程是一個更加接近于執行體的概念,它可以與同進程中的其他線程共享數據,但擁有自己的棧空間,擁有獨立的執行序列。
3.區別
進程和線程的主要差別在于它們是不同的操作系統資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響。
而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,
所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。
但對于一些要求同時進行并且又要共享某些變量的并發操作,只能用線程,不能用進程。
1) 簡而言之,一個程序至少有一個進程,一個進程至少有一個線程.
2) 線程的劃分尺度小于進程,使得多線程程序的并發性高。
3) 另外,進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大地提高了程序的運行效率。
4) 線程在執行過程中與進程還是有區別的。每個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口。
? ?但是線程不能夠獨立執行,必須依存在應用程序中,由應用程序提供多個線程執行控制。
5) 從邏輯角度來看,多線程的意義在于一個應用程序中,有多個執行部分可以同時執行。
? ?但操作系統并沒有將多個線程看做多個獨立的應用,來實現進程的調度和管理以及資源分配。這就是進程和線程的重要區別。
4.優缺點
線程和進程在使用上各有優缺點:
線程執行開銷小,但不利于資源的管理和保護;而進程正相反。
舉例
開個QQ,開了一個進程;開了迅雷,開了一個進程。在QQ的這個進程里,傳輸文字開一個線程、傳輸語音開了一個線程、彈出對話框又開了一個線程。Why:?
由于CPU與其他PC資源之間速度的不協調,人們想提高資源利用率,所以人們提出了多任務系統。
得益于CPU的計算速度,我們可以“同時”運行多個任務,實質上是多個任務之間輪流使用CPU資源,由于速度超快,給用戶的感覺就是連續的。
How:?
1)任務的執行需要依賴各個PC資源,我們可以稱為計算機執行的上下文環境。
? ?要實現“同時執行”,就需要不斷輪換,為了后來繼續從當前狀態執行下去,計算機需要保存切換前的程序上下文。
? ?所以有了進程:用進程去描述程序當前上下文的狀態信息----內存位置、變量值、任務ID……所以,進程是資源分配的單位。
? ?一般來說宏觀上可以看做是一個軟件的運行,例如一個word文檔的打開。
2)多個任務之間切換因為要保存上下文、調入上下文,一旦多了的時候,還是有一定的時間消耗的。
? ?為了進一步提高資源利用率,人們在進程中,引入了線程,線程只是CPU輪流調度的單位,其他上下文信息用所在進程中的。
? ?這樣上下文切換的耗時就降了下來。同樣的,宏觀上來可以看做是一個軟件中的多個處理功能,例如上述打開word中拼寫檢查功能、字體加粗……
So, What:?
一般來說,進程是資源的分配單位,線程是CPU在進程內切換的單位,線程屬于進程。所以運行某個軟件,相當于開了一個進程。
在這個軟件運行的過程里(在這個進程里),多個工作支撐的完成QQ的運行,那么這“多個工作”分別有一個線程。
再打一個通俗易懂的比方吧!
比如你去一個食堂吃飯。里面有A,B,C,D等一些窗口可以打飯菜或者米粉麻辣燙什么的。
但是每一個窗口又有打這些菜的師傅。
那么這些窗口就是進程。
那個那些窗口里面打菜的師傅就是線程。
這個食堂就是系統了,系統去分配這些進程。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的同步与异步以及线程与进程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Jmeter BeanShell取样器操
- 下一篇: Pytest之pytest-assume