【java】【多執行緒】程式、執行緒的基本概念(1)

love_Aym發表於2018-04-13

執行緒和程式的深刻解釋:https://blog.csdn.net/luoweifu/article/details/46595285(原文)

java中的多執行緒:https://blog.csdn.net/luoweifu/article/details/46673975


一、程式

  • 計算機的核心是CPU,它承擔了所有的計算任務
  • 作業系統是計算機的管理者,它負責任務的排程、資源的分配和管理,統領整個計算機硬體;
  • 應用程式是具有某種功能的程式,程式是執行於作業系統之上的。
    程式:是一個具有一定獨立功能的程式在一個資料集上的一次動態執行的過程,是作業系統進行資源分配和排程的一個獨立單位,是應用程式執行的載體。程式是一種抽象的概念,從來沒有統一的標準定義。

    程式一般由程式、資料集合和程式控制塊三部分組成。

  • 程式用於描述程式要完成的功能,是控制程式執行的指令集;
  • 資料集合是程式在執行時所需要的資料和工作區;
  • 程式控制塊(Program Control Block,簡稱PCB)包含程式的描述資訊和控制資訊,是程式存在的唯一標誌。

程式具有的特徵:

動態性:程式是程式的一次執行過程,是臨時的,有生命期的,是動態產生,動態消亡的;

併發性:任何程式都可以同其他程式一起併發執行;

獨立性:程式是系統進行資源分配和排程的一個獨立單位;

結構性:程式由程式、資料和程式控制塊三部分組成。

要理解執行緒是什麼,須要先了解作業系統的一些概念。

二、任務排程

        大部分作業系統(WindowsLinux)的任務排程是採用時間片輪轉的搶佔式排程方式,也就是說一個任務執行一小段時間後強制暫停去執行下一個任務,每個任務輪流執行。

        任務執行的一小段時間叫做時間片,任務正在執行時的狀態叫執行狀態,任務執行一段時間後強制暫停去執行下一個任務,被暫停的任務就處於就緒狀態等待下一個屬於它的時間片的到來。這樣每個任務都能得到執行,由於CPU的執行效率非常高,時間片非常短,在各個任務之間快速地切換,給人的感覺就是多個任務在“同時進行”,這也就是我們所說的併發。 (別覺得併發有多高深,它的實現很複雜,但它的概念很簡單,就是一句話:多個任務同時執行)

併發和並行的區別:

  • 併發:一個處理器,多個任務請求,快速切換,達到虛擬的同時進行。兩個任務都請求執行,而處理器只能按受一個任務,就把這兩個任務安排輪流進行,由於時間間隔較短,使人感覺兩個任務都在執行。
  • 並行:多個處理器,多個任務,同時進行,名副其實的同時進行。兩個任務同時執行,甲任務進行的同時,乙任務也在進行。(需要多核CPU)



三、執行緒

     在早期的作業系統中並沒有執行緒的概念,程式是能擁有資源和獨立執行的最小單位,也是程式執行的最小單位。任務排程採用的是時間片輪轉的搶佔式排程方式,而程式是任務排程的最小單位,每個程式有各自獨立的一塊記憶體,使得各個程式之間記憶體地址相互隔離。


圖 4早期的作業系統只有程式,沒有執行緒

    後來,隨著計算機的發展,對CPU的要求越來越高,程式之間的切換開銷較大,已經無法滿足越來越複雜的程式的要求了。於是就發明了執行緒,執行緒是程式執行中一個單一的順序控制流程,是程式執行流的最小單元,是處理器排程和分派的基本單位


圖 5:執行緒的出現,使得一個程式可以有多個執行緒

下圖是來自知乎使用者的解釋:

這裡寫圖片描述


四、程式與執行緒的關係和區別

  1. 程式是作業系統分配資源的最小單位,而執行緒是程式執行的最小單位
  2. 一個程式由一個或多個執行緒組成,執行緒是一個程式中程式碼的不同執行路線,各個執行緒之間共享程式的記憶體空間(所在程式的記憶體空間)
  3. 程式由記憶體空間(程式碼、資料、程式空間、開啟的檔案)和一個或多個執行緒組成。一個標準的執行緒由執行緒ID、當前指令指標(PC)、暫存器和堆疊組成。
  4. 程式之間相互獨立,但同一程式下的各個執行緒之間共享程式的記憶體空間及一些程式級的資源(如開啟檔案和訊號),某程式內的執行緒在其它程式不可見;
  5. 排程和切換:執行緒上下文切換比程式上下文切換要快得多。


圖 2程式與執行緒的資源共享關係


圖 3:單執行緒與多執行緒的關係

五、總結

  •  執行緒和程式都是一種抽象的概念,執行緒是一種比程式更小的抽象,執行緒和程式都可用於實現併發。
  • 在早期的作業系統中並沒有執行緒的概念,程式是能擁有資源和獨立執行的最小單位,也是程式執行的最小單位。它相當於一個程式裡只有一個執行緒,程式本身就是執行緒。所以執行緒有時被稱為輕量級程式(Lightweight ProcessLWP)。、
  • 後來,隨著計算機的發展,對多個任務之間上下文切換的效率要求越來越高,就抽象出一個更小的概念——執行緒,一般一個程式會有多個(也可是一個)執行緒。
  • 來自  https://blog.csdn.net/xlgen157387/article/details/77920497  的解釋
    1)程式(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。在早期面向程式設計的計算機結構中,程式是程式的基本執行實體;在當代面向執行緒設計的計算機結構中,程式是執行緒的容器。程式是指令、資料及其組織形式的描述,程式是程式的實體。

   2)執行緒,有時被稱為輕量級程式(Lightweight Process,LWP),是程式執行流的最小單元。執行緒是程式中一個單一的順序控制流程。程式內一個相對獨立的、可排程的執行單元,是系統獨立排程和分派CPU的基本單位指執行中的程式的排程單位。在單個程式中同時執行多個執行緒完成不同的工作,稱為多執行緒。


1、Java程式執行原理

        由Java命令啟動java虛擬機器,啟動JVM就等於啟動了一個應用程式,也就是啟動了一個程式。該程式會自動啟動一個“主執行緒“,然後主執行緒去呼叫某個類的 main 方法。

2、JVM的啟動是多執行緒的嗎?   是。

        除了主執行緒,垃圾回收執行緒也要先啟動,否則很容易會出現記憶體溢位。因此,JVM啟動至少啟動了垃圾回收執行緒和主執行緒,所以是多執行緒的。


六、使用者執行緒與核心執行緒的對應關係

    先了解一下多執行緒與多核

      上面提到的時間片輪轉的排程方式說一個任務執行一小段時間後強制暫停去執行下一個任務,每個任務輪流執行。很多作業系統的書都說“同一時間點只有一個任務在執行”。那有人可能就要問雙核處理器呢?難道兩個核不是同時執行嗎?

      其實“同一時間點只有一個任務在執行”這句話是不準確的,至少它是不全面的。那多核處理器的情況下,執行緒是怎樣執行呢?這就需要了解核心執行緒。

     多核()處理器是指在一個處理器上整合多個運算核心從而提高計算能力,也就是有多個真正平行計算的處理核心,每一個處理核心對應一個核心執行緒。核心執行緒(Kernel Thread, KLT就是直接由作業系統核心支援的執行緒,這種執行緒由核心來完成執行緒切換,核心通過操作排程器對執行緒進行排程,並負責將執行緒的任務對映到各個處理器上。一般一個處理核心對應一個核心執行緒,比如單核處理器對應一個核心執行緒,雙核處理器對應兩個核心執行緒,四核處理器對應四個核心執行緒。

      現在的電腦一般是雙核四執行緒、四核八執行緒,是採用超執行緒技術將一個物理處理核心模擬成兩個邏輯處理核心,對應兩個核心執行緒,所以在作業系統中看到的CPU數量是實際物理CPU數量的兩倍,如你的電腦是雙核四執行緒,開啟“工作管理員\效能”可以看到4CPU的監視器,四核八執行緒可以看到8CPU的監視器。


圖 6:雙核四執行緒在Windows8下檢視的結果

      超執行緒技術就是利用特殊的硬體指令,把一個物理晶片模擬成兩個邏輯處理核心,讓單個處理器都能使用執行緒級平行計算,進而相容多執行緒作業系統和軟體,減少了CPU的閒置時間,提高的CPU的執行效率。這種超執行緒技術(如雙核四執行緒)由處理器硬體的決定,同時也需要作業系統的支援才能在計算機中表現出來。 

       程式一般不會直接去使用核心執行緒,而是去使用核心執行緒的一種高階介面——輕量級程式(Light Weight ProcessLWP),輕量級程式就是我們通常意義上所講的執行緒(我們在這稱它為使用者執行緒),由於每個輕量級程式都由一個核心執行緒支援,因此只有先支援核心執行緒,才能有輕量級程式。

        使用者執行緒與核心執行緒的對應關係有三種模型:一對一模型、多對一模型、多對多模型,在這以4個核心執行緒、3個使用者執行緒為例對三種模型進行說明。


1、一對一模型

       對於一對一模型來說,一個使用者執行緒就唯一地對應一個核心執行緒(反過來不一定成立,一個核心執行緒不一定有對應的使用者執行緒)。這樣,如果CPU沒有采用超執行緒技術(如四核四執行緒的計算機),一個使用者執行緒就唯一地對映到一個物理CPU的執行緒,執行緒之間的併發是真正的併發。一對一模型使使用者執行緒具有與核心執行緒一樣的優點,一個執行緒因某種原因阻塞時其他執行緒的執行不受影響;此處,一對一模型也可以讓多執行緒程式在多處理器的系統上有更好的表現。

      但一對一模型也有兩個缺點:

  1. 許多作業系統限制了核心執行緒的數量,因此一對一模型會使使用者執行緒的數量受到限制;
  2. 許多作業系統核心執行緒排程時,上下文切換的開銷較大,導致使用者執行緒的執行效率下降。

 

 

圖 7:一對一模型

2、多對一模型

        多對一模型將多個使用者執行緒對映到一個核心執行緒上,執行緒之間的切換由使用者態的程式碼來進行,因此相對一對一模型,多對一模型的執行緒切換速度要快許多;此外,多對一模型對使用者執行緒的數量幾乎無限制。

        但多對一模型也有兩個缺點:

  1. 如果其中一個使用者執行緒阻塞,那麼其它所有執行緒都將無法執行,因為此時核心執行緒也隨之阻塞了;
  2. 在多處理器系統上,處理器數量的增加對多對一模型的執行緒效能不會有明顯的增加,因為所有的使用者執行緒都對映到一個處理器上了。

 

圖 8:多對一模型

3、多對多模型

    多對多模型結合了一對一模型和多對一模型的優點,將多個使用者執行緒對映到多個核心執行緒上。

    多對多模型的優點有:

  1. 一個使用者執行緒的阻塞不會導致所有執行緒的阻塞,因為此時還有別的核心執行緒被排程來執行;
  2. 多對多模型對使用者執行緒的數量沒有限制;
  3. 在多處理器的作業系統中,多對多模型的執行緒也能得到一定的效能提升,但提升的幅度不如一對一模型的高。

      在現在流行的作業系統中,大都採用多對多的模型。

 

圖 9:多對多模型


七、執行緒的生命週期

       當執行緒的數量小於處理器的數量時,執行緒的併發是真正的併發,不同的執行緒執行在不同的處理器上。但當執行緒的數量大於處理器的數量時,執行緒的併發會受到一些阻礙,此時並不是真正的併發,因為此時至少有一個處理器會執行多個執行緒。

       在單個處理器執行多個執行緒時,併發是一種模擬出來的狀態。作業系統採用時間片輪轉的方式輪流執行每一個執行緒。現在,幾乎所有的現代作業系統採用的都是時間片輪轉的搶佔式排程方式,如我們熟悉的UnixLinuxWindowsMac OS X等流行的作業系統。

       我們知道執行緒是程式執行的最小單位,也是任務執行的最小單位。在早期只有程式的作業系統中,程式有五種狀態,建立、就緒、執行、阻塞(等待)、退出。早期的程式相當於現在的只有單個執行緒的程式,那麼現在的多執行緒也有五種狀態,現在的多執行緒的生命週期與早期程式的生命週期類似。

 

圖 12:早期程式的生命週期


       程式在執行過程有三種狀態:就緒、執行、阻塞,建立和退出狀態描述的是程式的建立過程和退出過程。

  • 建立:程式正在建立,還不能執行。作業系統在建立程式時要進行的工作包括分配和建立程式控制塊表項、建立資源表格並分配資源、載入程式並建立地址空間;
  • 就緒:時間片已用完,此執行緒被強制暫停,等待下一個屬於他的時間片到來;
  • 執行:此執行緒正在執行,正在佔用時間片;
  • 阻塞:也叫等待狀態,等待某一事件(IO或另一個執行緒)執行完;
  • 退出:程式已結束,所以也稱結束狀態,釋放作業系統分配的資源。

 

圖 13:執行緒的生命週期

  • 建立:一個新的執行緒被建立,等待該執行緒被呼叫執行;
  • 就緒:時間片已用完,此執行緒被強制暫停,等待下一個屬於他的時間片到來;
  • 執行:此執行緒正在執行,正在佔用時間片;
  • 阻塞:也叫等待狀態,等待某一事件(IO或另一個執行緒)執行完;
  • 退出:一個執行緒完成任務或者其他終止條件發生,該執行緒終止進入退出狀態,退出狀態釋放該執行緒所分配的資源。



相關文章