從硬件的角度區(qū)分進(jìn)程和線程
進(jìn)程(process)和線程(thread)是操作系統(tǒng)的基本概念,但是比較抽象,不容易掌握。

上圖表明,一個(gè)程序要能夠運(yùn)行,必須獲得相應(yīng)的內(nèi)存等資源。
1.線程是進(jìn)程內(nèi)的一個(gè)相對(duì)獨(dú)立的可執(zhí)行的單元。若把進(jìn)程稱為任務(wù)的話,那么線程則是應(yīng)用中的一個(gè)子任務(wù)的執(zhí)行。
2.由于線程是被調(diào)度的基本單元,而進(jìn)程不是調(diào)度單元。所以,每個(gè)進(jìn)程在創(chuàng)建時(shí),至少需要同時(shí)為該進(jìn)程創(chuàng)建一個(gè)線程。即進(jìn)程中至少要有一個(gè)或一個(gè)以上的線程,否則該進(jìn)程無法被調(diào)度執(zhí)行。
3.進(jìn)程是被分配并擁有資源的基本單元。同一進(jìn)程內(nèi)的多個(gè)線程共享該進(jìn)程的資源,但線程并不擁有資源,只是使用他們。
4.線程是操作系統(tǒng)中基本調(diào)度單元,因此線程中應(yīng)包含有調(diào)度所需要的必要信息,且在生命周期中有狀態(tài)的變化。
5.由于共享資源【包括數(shù)據(jù)和文件】,所以線程間需要通信和同步機(jī)制,且需要時(shí)線程可以創(chuàng)建其他線程,但線程間不存在父子關(guān)系。
上述這段話的意思就是,CPU分配內(nèi)存等資源的時(shí)候是以進(jìn)程為單位(進(jìn)程控制塊PCB),線程沒有資格獲得資源,而真正執(zhí)行程序的時(shí)候是以線程為單位。我們知道,一個(gè)經(jīng)過編譯后裝入內(nèi)存準(zhǔn)備執(zhí)行的程序就是一個(gè)進(jìn)程。
所謂的調(diào)度,從CPU的內(nèi)部結(jié)構(gòu)來看,就是某個(gè)函數(shù)的入口地址裝入了PC寄存器,而這里的函數(shù)就是一個(gè)線程。

為了進(jìn)一步理解清楚進(jìn)程與線程間的資源分配關(guān)系,這里轉(zhuǎn)載一個(gè)關(guān)于它們之間區(qū)別的形象描述:
1.

計(jì)算機(jī)的核心是CPU,它承擔(dān)了所有的計(jì)算任務(wù)。它就像一座工廠,時(shí)刻在運(yùn)行。
2.假定工廠的電力有限,一次只能供給一個(gè)車間使用。也就是說,一個(gè)車間開工的時(shí)候,其他車間都必須停工。背后的含義就是,單個(gè)CPU一次只能運(yùn)行一個(gè)任務(wù)。
3.

進(jìn)程就好比工廠的車間,它代表CPU所能處理的單個(gè)任務(wù)。任一時(shí)刻,CPU總是運(yùn)行一個(gè)進(jìn)程,其他進(jìn)程處于非運(yùn)行狀態(tài)。
4.一個(gè)車間里,可以有很多工人。他們協(xié)同完成一個(gè)任務(wù)。
5.

線程就好比車間里的工人。一個(gè)進(jìn)程可以包括多個(gè)線程。
6.

車間的空間是工人們共享的,比如許多房間是每個(gè)工人都可以進(jìn)出的。這象征一個(gè)進(jìn)程的內(nèi)存空間是共享的,每個(gè)線程都可以使用這些共享內(nèi)存。
7.可是,每間房間的大小不同,有些房間最多只能容納一個(gè)人,比如廁所。里面有人的時(shí)候,其他人就不能進(jìn)去了。這代表一個(gè)線程使用某些共享內(nèi)存時(shí),其他線程必須等它結(jié)束,才能使用這一塊內(nèi)存。
8.

一個(gè)防止他人進(jìn)入的簡單方法,就是門口加一把鎖。先到的人鎖上門,后到的人看到上鎖,就在門口排隊(duì),等鎖打開再進(jìn)去。這就叫"互斥鎖"(Mutual exclusion,縮寫 Mutex),防止多個(gè)線程同時(shí)讀寫某一塊內(nèi)存區(qū)域。
9.還有些房間,可以同時(shí)容納n個(gè)人,比如廚房。也就是說,如果人數(shù)大于n,多出來的人只能在外面等著。這好比某些內(nèi)存區(qū)域,只能供給固定數(shù)目的線程使用。
10.

這時(shí)的解決方法,就是在門口掛n把鑰匙。進(jìn)去的人就取一把鑰匙,出來時(shí)再把鑰匙掛回原處。后到的人發(fā)現(xiàn)鑰匙架空了,就知道必須在門口排隊(duì)等著了。這種做法叫做"信號(hào)量"(Semaphore),用來保證多個(gè)線程不會(huì)互相沖突。
不難看出,mutex是semaphore的一種特殊情況(n=1時(shí))。也就是說,完全可以用后者替代前者。但是,因?yàn)閙utex較為簡單,且效率高,所以在必須保證資源獨(dú)占的情況下,還是采用這種設(shè)計(jì)。
11.操作系統(tǒng)的設(shè)計(jì),因此可以歸結(jié)為三點(diǎn):
(1)以多進(jìn)程形式,允許多個(gè)任務(wù)同時(shí)運(yùn)行;
(2)以多線程形式,允許單個(gè)任務(wù)分成不同的部分運(yùn)行;
(3)提供協(xié)調(diào)機(jī)制,一方面防止進(jìn)程之間和線程之間產(chǎn)生沖突,另一方面允許進(jìn)程之間和線程之間共享資源。
再看看創(chuàng)建一個(gè)線程時(shí)候的數(shù)據(jù)結(jié)構(gòu):

可以看到,每個(gè)被創(chuàng)建的線程都有自己的名字、參數(shù)和入口地址,和通常的函數(shù)是一樣的。
下面引述一個(gè)網(wǎng)絡(luò)上的例子做進(jìn)一步的闡述:



從這個(gè)程序本身及其運(yùn)行結(jié)果我們可以看到,線程由主函數(shù)創(chuàng)建,但同時(shí)主函數(shù)本身也是一個(gè)線程,它與被自己創(chuàng)建的線程一起參與被CPU調(diào)度執(zhí)行的過程,而這種調(diào)度是一種隨機(jī)的過程,這一點(diǎn)從程序的運(yùn)行結(jié)果可以看出來。
再看一下線程調(diào)度的大概過程:

從圖中可以看出,每個(gè)線程都有不同的狀態(tài),什么時(shí)候哪個(gè)線程獲得執(zhí)行權(quán)是一個(gè)隨機(jī)的過程,這其中的實(shí)現(xiàn)機(jī)制我們不必要去管,也許是通過一個(gè)隨機(jī)數(shù)實(shí)現(xiàn),我們這里關(guān)注的是
CPU的調(diào)度對(duì)象是線程而不是進(jìn)程。
簡單總結(jié):
1:進(jìn)程是資源的分配對(duì)象,而線程是調(diào)度對(duì)象。
2:一個(gè)進(jìn)程中可以有若干個(gè)線程。
3:程序中的主函數(shù)也是一個(gè)線程,它與被它創(chuàng)建的線程一樣,平等地參與被CPU的調(diào)度過程。
4:線程本身沒有資源擁有權(quán),只能和其它線程共享進(jìn)程資源。