線程與進(jìn)程是操作系統(tǒng)里面的術(shù)語,簡單來講,每一個(gè)應(yīng)用程序都有一個(gè)自己的進(jìn)程。
操作系統(tǒng)會(huì)為這些進(jìn)程分配一些執(zhí)行資源,例如內(nèi)存空間等。在進(jìn)程中,又可以創(chuàng)建一些線程,他們共享這些內(nèi)存空間,并由操作系統(tǒng)調(diào)用,以便并行計(jì)算。
我們都知道現(xiàn)代操作系統(tǒng)比如 Mac OS X,UNIX,Linux,Windows 等可以同時(shí)運(yùn)行多個(gè)任務(wù)。打個(gè)比方,你一邊在用瀏覽器上網(wǎng),一邊在聽敲代碼,一邊用 Markdown 寫博客,這就是多任務(wù),至少同時(shí)有 3 個(gè)任務(wù)正在運(yùn)行。當(dāng)然還有很多任務(wù)悄悄地在后臺(tái)同時(shí)運(yùn)行著,只是桌面上沒有顯示而已。對(duì)于操作系統(tǒng)來說,一個(gè)任務(wù)就是一個(gè)進(jìn)程(Process),比如打開一個(gè)瀏覽器就是啟動(dòng)一個(gè)瀏覽器進(jìn)程,打開 PyCharm 就是一個(gè)啟動(dòng)了一個(gè) PtCharm 進(jìn)程,打開 Markdown 就是啟動(dòng)了一個(gè) Md 的進(jìn)程。
雖然現(xiàn)在多核 CPU 已經(jīng)非常普及了??墒怯捎?CPU 執(zhí)行代碼都是順序執(zhí)行的,這時(shí)候我們就會(huì)有疑問,單核 CPU 是怎么執(zhí)行多任務(wù)的呢?
其實(shí)就是操作系統(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上沒法識(shí)別出來,就像所有任務(wù)都在同時(shí)執(zhí)行一樣。
真正的并行執(zhí)行多任務(wù)只能在多核 CPU 上實(shí)現(xiàn),但是,由于任務(wù)數(shù)量遠(yuǎn)遠(yuǎn)多于 CPU 的核心數(shù)量,所以,操作系統(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è)進(jìn)程至少要干一件事,所以,一個(gè)進(jìn)程至少有一個(gè)線程。當(dāng)然,一個(gè)進(jìn)程也可以有多個(gè)線程,多個(gè)線程可以同時(shí)執(zhí)行,多線程的執(zhí)行方式和多進(jìn)程是一樣的,也是由操作系統(tǒng)在多個(gè)線程之間快速切換,讓每個(gè)線程都短暫地交替運(yùn)行,看起來就像同時(shí)執(zhí)行一樣。
那么在 Python 中我們要同時(shí)執(zhí)行多個(gè)任務(wù)怎么辦?
有兩種解決方案:
一種是啟動(dòng)多個(gè)進(jìn)程,每個(gè)進(jìn)程雖然只有一個(gè)線程,但多個(gè)進(jìn)程可以一塊執(zhí)行多個(gè)任務(wù)。
還有一種方法是啟動(dòng)一個(gè)進(jìn)程,在一個(gè)進(jìn)程內(nèi)啟動(dòng)多個(gè)線程,這樣,多個(gè)線程也可以一塊執(zhí)行多個(gè)任務(wù)。
當(dāng)然還有第三種方法,就是啟動(dòng)多個(gè)進(jìn)程,每個(gè)進(jìn)程再啟動(dòng)多個(gè)線程,這樣同時(shí)執(zhí)行的任務(wù)就更多了,當(dāng)然這種模型更復(fù)雜,實(shí)際很少采用。
總結(jié)一下就是,多任務(wù)的實(shí)現(xiàn)有3種方式:
同時(shí)執(zhí)行多個(gè)任務(wù)通常各個(gè)任務(wù)之間并不是沒有關(guān)聯(lián)的,而是需要相互通信和協(xié)調(diào),有時(shí),任務(wù) 1 必須暫停等待任務(wù) 2 完成后才能繼續(xù)執(zhí)行,有時(shí),任務(wù) 3 和任務(wù) 4 又不能同時(shí)執(zhí)行,所以,多進(jìn)程和多線程的程序的復(fù)雜度要遠(yuǎn)遠(yuǎn)高于我們前面寫的單進(jìn)程單線程的程序。
因?yàn)閺?fù)雜度高,調(diào)試?yán)щy,所以,不是迫不得已,我們也不想編寫多任務(wù)。但是,有很多時(shí)候,沒有多任務(wù)還真不行。想想在電腦上看電影,就必須由一個(gè)線程播放視頻,另一個(gè)線程播放音頻,否則,單線程實(shí)現(xiàn)的話就只能先把視頻播放完再播放音頻,或者先把音頻播放完再播放視頻,這顯然是不行的。