執(zhí)行緒與行程
執(zhí)行緒與進(jìn)程是作業(yè)系統(tǒng)裡面的術(shù)語(yǔ),簡(jiǎn)單來(lái)講,每個(gè)應(yīng)用程式都有一個(gè)自己的行程。
作業(yè)系統(tǒng)會(huì)為這些行程分配一些執(zhí)行資源,例如記憶體空間等。在進(jìn)程中,又可以創(chuàng)建一些線程,他們共享這些記憶體空間,並由作業(yè)系統(tǒng)調(diào)用,以便並行計(jì)算。
我們都知道現(xiàn)代作業(yè)系統(tǒng)像是 Mac OS X,UNIX,Linux,Windows 等可以同時(shí)執(zhí)行多個(gè)任務(wù)。打個(gè)比方,你一邊在用瀏覽器上網(wǎng),一邊在聽(tīng)敲代碼,一邊用 Markdown 寫(xiě)博客,這就是多任務(wù),至少同時(shí)有 3 個(gè)任務(wù)正在運(yùn)行。當(dāng)然還有很多任務(wù)悄悄地在後臺(tái)同時(shí)運(yùn)行著,只是桌面上沒(méi)有顯示而已。對(duì)作業(yè)系統(tǒng)來(lái)說(shuō),一個(gè)任務(wù)就是一個(gè)進(jìn)程(Process),例如開(kāi)啟一個(gè)瀏覽器就是啟動(dòng)一個(gè)瀏覽器進(jìn)程,開(kāi)啟 PyCharm 就是一個(gè)啟動(dòng)了一個(gè) PtCharm 進(jìn)程,而開(kāi)啟 Markdown 就是啟動(dòng)了一個(gè) Md 的進(jìn)程。
雖然現(xiàn)在多核心 CPU 已經(jīng)非常普及了。可是由於 CPU 執(zhí)行程式碼都是順序執(zhí)行的,這時(shí)候我們就會(huì)有疑問(wèn),單核心 CPU 是怎麼執(zhí)行多任務(wù)的呢?
其實(shí)就是作業(yè)系統(tǒng)輪流讓各個(gè)任務(wù)交替執(zhí)行,任務(wù)1 執(zhí)行0.01 秒,切換到任務(wù)2 ,任務(wù)2 執(zhí)行0.01 秒,再切換到任務(wù)3 ,執(zhí)行0.01秒…這樣反復(fù)執(zhí)行下去。表面上看,每個(gè)任務(wù)都是交替執(zhí)行的,但是,由於 CPU的執(zhí)行速度實(shí)在是太快了,我們?nèi)庋酆透杏X(jué)上沒(méi)辦法識(shí)別出來(lái),就像所有任務(wù)都在同時(shí)執(zhí)行一樣。
真正的平行執(zhí)行多任務(wù)只能在多核心CPU 上實(shí)現(xiàn),但是,由於任務(wù)數(shù)量遠(yuǎn)遠(yuǎn)多於CPU 的核心數(shù)量,所以,作業(yè)系統(tǒng)也會(huì)自動(dòng)把很多任務(wù)輪流調(diào)度到每個(gè)核心上執(zhí)行。
有些進(jìn)程不只是乾一件事的啊,比如瀏覽器,我們可以播放時(shí)視頻,播放音頻,看文章,編輯文章等等,其實(shí)這些都是在瀏覽器進(jìn)程中的子任務(wù)。在一個(gè)進(jìn)程內(nèi)部,要同時(shí)幹多件事,就需要同時(shí)運(yùn)行多個(gè)“子任務(wù)”,我們把進(jìn)程內(nèi)的這些“子任務(wù)”稱為線程(Thread)。
由於每個(gè)行程至少要做一件事,所以,一個(gè)行程至少有一個(gè)執(zhí)行緒。當(dāng)然,一個(gè)行程也可以有多個(gè)線程,多個(gè)線程可以同時(shí)執(zhí)行,多線程的執(zhí)行方式和多進(jìn)程是一樣的,也是由作業(yè)系統(tǒng)在多個(gè)線程之間快速切換,讓每個(gè)線程都短暫地交替運(yùn)行,看起來(lái)就像同時(shí)執(zhí)行一樣。
那麼在 Python 中我們要同時(shí)執(zhí)行多個(gè)任務(wù)怎麼辦?
有兩種解決方案:
一種是啟動(dòng)多個(gè)進(jìn)程,每個(gè)進(jìn)程雖然只有一個(gè)線程,但多個(gè)進(jìn)程可以一塊執(zhí)行多個(gè)任務(wù)。
還有一個(gè)方法是啟動(dòng)一個(gè)行程,在一個(gè)行程內(nèi)啟動(dòng)多個(gè)線程,這樣,多個(gè)執(zhí)行緒也可以一塊執(zhí)行多個(gè)任務(wù)。
當(dāng)然還有第三種方法,就是啟動(dòng)多個(gè)進(jìn)程,每個(gè)進(jìn)程再啟動(dòng)多個(gè)線程,這樣同時(shí)執(zhí)行的任務(wù)就更多了,當(dāng)然這種模型更複雜,實(shí)際上很少採(cǎi)用。
總結(jié)一下就是,多任務(wù)的實(shí)作有3種方式:
多進(jìn)程模式;
多執(zhí)行緒模式;
多行程多執(zhí)行緒模式。
同時(shí)執(zhí)行多個(gè)任務(wù)通常各個(gè)任務(wù)之間並不是沒(méi)有關(guān)聯(lián)的,而是需要相互溝通和協(xié)調(diào),有時(shí),任務(wù)1 必須暫停等待任務(wù)2 完成後才能繼續(xù)執(zhí)行,有時(shí),任務(wù)3 和任務(wù)4 又不能同時(shí)執(zhí)行,所以,多行程和多執(zhí)行緒的程式的複雜度要遠(yuǎn)高於我們前面寫(xiě)的單一行程單執(zhí)行緒的程式。
因?yàn)檠}雜度高,調(diào)試?yán)щy,所以,不是迫不得已,我們也不想寫(xiě)多任務(wù)。但是,有很多時(shí)候,沒(méi)有多工還真不行。想想在電腦上看電影,就必須由一個(gè)線程播放視頻,另一個(gè)線程播放音頻,否則,單線程實(shí)現(xiàn)的話就只能先把視頻播放完再播放音頻,或者先把音頻播放完再播放視頻,這顯然是不行的。