1. 程式人生 > 實用技巧 >對執行緒與程序的區別以及對多執行緒併發的理解

對執行緒與程序的區別以及對多執行緒併發的理解

一、執行緒與程序的區別

先簡單說說執行緒與程序的概念:

(1)程序是指一個記憶體中執行的應用程式,比如在Windows系統中,一個執行的exe就是一個程序。

(2)執行緒是指程序中的一個執行流程。

區別:

一個程式至少有一個程序,而一個程序至少有一個執行緒。一個應用程式可以同時啟動多個程序。例如對於IE瀏覽器程式,每開啟一個IE瀏覽器視窗,就啟動了一個新的程序。而執行緒則是指程序中的一個執行流程,一個程序可以有多個執行緒,每個執行緒分別執行不同的任務,當程序內的多個執行緒同時執行時,這種執行方式就被稱為併發執行。

另外,執行緒與程序還有一個非常重要的區別:每個程序在執行過程中都擁有獨立的記憶體單元,而同一個程序中的多個執行緒則共享記憶體,從而極大地提高了程式的執行效率。

二、對多執行緒併發的理解

多執行緒併發只是表面和感覺上的併發,並不是實質上的併發。一個執行緒要執行,它必須佔有CPU,而我們目前用的計算機大多都是單CPU的,所以一次最多隻能有一個執行緒獲取CPU並執行。

多執行緒的實質是“最大限度地利用CPU資源”,當某一個執行緒的處理不需要佔用CPU而只需要和I/O等資源打交道時,讓其他執行緒有機會獲得CPU資源。這有點類似於“統籌方法”,例如讓你打掃房子和燒水,要在最短的時間內做好這兩件事,你一定會想到先把水燒上,然後在等水燒開的空閒時間中去打掃房子,而不是先打掃好了再去燒水,也不是先燒好了再去打掃,這個例子裡面,你是那個唯一的CPU,而燒水和打掃就是兩個執行緒。

雖然CPU只有一個,但是它在多個執行緒之間頻繁切換,當切換的頻率高到一定程度時,我們就感覺所有的執行緒在同時執行,於是感覺這多個執行緒是併發的。因此,併發並不是真的指多個執行緒同時執行,它僅僅只是形容一種現象。就好像說有些人是“鐵人”一樣,僅僅只是用於形容某個人不怕苦不怕累,像個“鐵人”。

1. 併發:在作業系統中,是指一個時間段中有幾個程式都處於已啟動執行到執行完畢之間,且這幾個程式都是在同一個處理機上執行。其中兩種併發關係分別是同步和互斥

2. 互斥:程序間相互排斥的使用臨界資源的現象,就叫互斥。

3. 同步:程序之間的關係不是相互排斥臨界資源的關係,而是相互依賴的關係。進一步的說明:就是前一個程序的輸出作為後一個程序的輸入,當第一個程序沒有輸出時第二個程序必須等待。具有同步關係的一組併發程序相互發送的資訊稱為訊息或事件。

其中併發又有偽併發和真併發,偽併發是指單核處理器的併發,真併發是指多核處理器的併發。

4. 並行:在單處理器中多道程式設計系統中,程序被交替執行,表現出一種併發的外部特種;在多處理器系統中,程序不僅可以交替執行,而且可以重疊執行。在多處理器上的程式才可實現並行處理。從而可知,並行是針對多處理器而言的。並行是同時發生的多個併發事件,具有併發的含義,但併發不一定並行,也亦是說併發事件之間不一定要同一時刻發生。

5. 多執行緒:多執行緒是程式設計的邏輯層概念,它是程序中併發執行的一段程式碼。多執行緒可以實現執行緒間的切換執行。

6. 非同步:非同步和同步是相對的,同步就是順序執行,執行完一個再執行下一個,需要等待、協調執行。非同步就是彼此獨立,在等待某事件的過程中繼續做自己的事,不需要等待這一事件完成後再工作。執行緒就是實現非同步的一個方式。非同步是讓呼叫方法的主執行緒不需要同步等待另一執行緒的完成,從而可以讓主執行緒幹其它的事情。

非同步和多執行緒並不是一個同等關係,非同步是最終目的,多執行緒只是我們實現非同步的一種手段。非同步是當一個呼叫請求傳送給被呼叫者,而呼叫者不用等待其結果的返回而可以做其它的事情。實現非同步可以採用多執行緒技術或則交給另外的程序來處理。

為了對以上概念的更好理解舉一個簡單例子, 假設我要做 燒開水,舉槓鈴100下, 洗衣服 3件事情。

燒開水 這件事情, 我要做的事情為, 準備燒開水 1分鐘, 等開水燒開 8 分鐘 , 關掉燒水機 1分鐘

舉槓鈴100下 我要做的事情為, 舉槓鈴100下 10分鐘

洗衣服 我要做的事情為, 準備洗衣服 1分鐘, 等開水燒開 5 分鐘 , 關掉洗衣機 1分鐘

單核情況下

同步的完成,我需要做的時間為 1+ 8 +1 + 10 + 1+ 5 +1 = 27 分

如果非同步,就是在等的時候,我可以切換去做別的事情

準備燒開水(1) + 準備洗衣服(1) + 舉50下槓鈴 (5)分鐘+ 關洗衣機 1分鐘 + 舉槓鈴20下 (2)分鐘+ 關燒水機 1分鐘 + 舉30下槓鈴(3)分鐘

1+1+5+1+2+1+3 =14 分鐘

雙核 非同步 並行

核1 準備燒開水 1分鐘+ 舉槓鈴50下(5)分鐘+ 等待3分鐘 + 關掉燒水機 1分鐘

核2 準備洗衣服 1分鐘+ 舉槓鈴50下(5)分鐘+ 關掉洗衣機 1分鐘 + 等待3分鐘

其實只花了 1+5+3+1 = 10分鐘

其中還有雙核都等待了3分鐘

雙核 非同步 非並行

核1 舉槓鈴100下(10)分鐘

核2 準備燒開水 1分鐘+ 準備洗衣服 1分鐘+ 等待5 分鐘+ + 關掉燒水機 1分鐘 + 等待 1 分鐘 + 關掉洗衣機 1分鐘

其實只花了 1+5+3+1 = 10分鐘

多執行緒的做法

單核下

執行緒1 準備燒開水 1分鐘, 等開水燒開 8 分鐘 , 關掉燒水機 1分鐘

執行緒2 舉槓鈴100下 10分鐘

執行緒3 準備洗衣服 1分鐘, 等開水燒開 5 分鐘 , 關掉洗衣機 1分鐘

cpu 可能這麼切換 最理想的切換方式

執行緒1 準備燒開水1 sleep 1 sleep 5 sleep 1 sleep 2 關開水 1分鐘 exit

執行緒2 sleep 1 sleep 1 舉槓鈴50 5分鐘 sleep 1 舉槓鈴20 2分鐘 sleep1 舉槓鈴30下 3分鐘

執行緒3 sleep 1 準備洗衣服1 分鐘 sleep 5 關洗衣機1分鐘 exit

最後使用了 14分鐘 和非同步是一樣的。

但是實際上是不一樣的,因為執行緒不會按照我們設想的去跑, 如果執行緒2 舉槓鈴先跑,整個流程的速度就下來了。

非同步和同步的區別, 在io等待的時候,同步不會切走,浪費了時間。

如果都是獨佔cpu 的業務, 比如舉槓鈴的業務, 在單核情況下 多線和單線 沒有區別。

多執行緒的好處,比較容易的實現了 非同步切換的思想, 因為非同步的程式很難寫的。多執行緒本身程還是以同步完成,但是應該說

比效率是比不上非同步的。 而且多線很容易寫, 相對效率也高。

多核的好處,就是可以同時做事情, 這個和單核完全不一樣的。

技術圖片