算法概念
假設計算機只有一個 CPU ,則在任意時刻只能執行一條機器指令,每個線程只有獲得 CPU 的使用權才能執行指令。
- 所謂多線程的並發運行,其實是指從宏觀上看,各個線程輪流獲得 CPU 的使用權,分別執行各自的任務。
- 在運行池中,會有多個處於就緒狀態的線程在等待 CPU ,Java 虛擬機的一項任務就是負責線程的調度,線程調度是指按照特定機制為多個線程分配 CPU 的使用權。
有兩種調度模型:分時調度模型和搶占式調度模型。
- 分時調度模型是指讓所有的線程輪流獲得 CPU 的使用權,並且平均分配每個線程占用的 CPU 的時間片這個也比較好理解。 。
- Java 虛擬機采用搶占式調度模型,是指優先讓可運行池中優先級高的線程占用 CPU ,如果可運行池中的線程優先級相同,那么就隨機選擇一個線程,使其占用 CPU 。處於運行狀態的線程會一直運行,直至它不得不放棄CPU 。
(用戶空間和內核空間)
線程飢餓概念
飢餓,一個或者多個線程因為種種原因無法獲得所需要的資源,導致一直無法執行的狀態。
Java 中導致飢餓的原因:
- 高優先級線程吞噬所有的低優先級線程的 CPU 時間。
- 線程被永久堵塞在一個等待進入同步塊的狀態,因為其他線程總是能在它之前持續地對該同步塊進行訪問。
- 線程在等待一個本身也處於永久等待完成的對象(比如調用這個對象的 wait 方法),因為其他線程總是被持續地獲得喚醒。
線程優化級概念
每一個線程都是有優先級的,一般來說,高優先級的線程在運行時會具有優先權,但這依賴於線程調度的實
現,這個實現是和操作系統相關的(OS dependent)。
- 我們可以定義線程的優先級,但是這並不能保證高優先級的線程會在低優先級的線程前執行。線程優先級是一個 int 變量(從1-10),1 代表最低優先級,10 代表最高優先級。
- Java 的線程優先級調度會委托給操作系統去處理,所以與具體的操作系統優先級有關,如非特別需要,一般無需設置線程優先級。
進程
概念
計算機的核心是CPU,它承擔了所有的計算任務,而操作系統是計算機的管理者,它負責任務的調度,資源的分配和管理,統領整個計算機硬件;應用程序是具有某種功能的程序,程序是運行於操作系統之上的。
進程是一個具有一定獨立功能的程序在一個數據集上的一次動態執行的過程,是操作系統進行資源分配和調度的一個獨立單位,是應用程序運行的載體。進程是一種抽象的概念,從來沒有統一的標准定義。
進程一般由程序,數據集合和進程控制塊三部分組成。
- 程序用於描述進程要完成的功能,是控制進程執行的指令集;
- 數據集合是程序在執行時所需要的數據和工作區;
- 程序控制塊包含進程的描述信息和是進程存在的唯一標志。
進程具有的特征:
動態性:進程是程序的一次執行過程,是臨時的,有生命期的,是動態產生,動態消亡的;
並發性:任何進程都可以同其他進程一起並發執行;
獨立性:進程是系統進行資源分配和調度的一個獨立單位;
結構性:進程由程序,數據和進程控制塊三部分組成。
線程
概念
在早期的操作系統中並沒有線程的概念,進程是擁有資源和獨立運行的最小單位,也是程序執行的最小單位。任務調度采用的是時間片輪轉的搶占式調度方式,而進程是任務調度的最小單位,每個進程有各自獨立的一塊內存,使得各個進程之間內存地址相互隔離。
后來隨着計算機的發展,對CPU的要求越來越高,進程之間的切換開銷較大,已經無法滿足越來越復雜的程序的要求了。於是就發明了線程,線程是程序執行中一個單一的順序控制流程,是程序執行流的最小單元,是處理器調度和分派的基本單位。一個進程可以有一個或多個線程,各個線程之間共享程序的內存空間(也就是所在進程的內存空間)。一個標准的線程由線程ID,當前指令指針PC,寄存器和堆棧組成。
而進程由內存空間(代碼,數據,進程空間,打開的文件)和一個或多個線程組成。
線程生命狀態
NEW--新建
RUNNABLE--運行
BLOCKED--阻塞
WAITTING--等待
TIMED_WAITTING--超時等待
TERMINATED--終結
生命周期
協程
概念
協程是一種用戶級的輕量級線程,一個線程可以有0到多個協程,協程本質是一個線程時間分片去執行協程代碼段。協程擁有自己的寄存器上下文和棧。協程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。協程能保留上一次調用時的狀態(即所有局部狀態的一個特定組合),每次過程重入時,就相當於進入上一次調用的狀態,換種說法:進入上一次離開時所處邏輯流的位置。
同一進程中,在多CPU的環境中,多線程可以並行,即多個線程同時在運行。
同一線程中,多協程只能並發,即同一時間只有一個協程在運行。
優點:
(1) 協程的執行效率非常高。因為子程序切換不是線程切換,而是由程序自身控制,因此,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。
(2)協程不需要多線程的鎖機制。在協程中控制共享資源不加鎖,只需要判斷狀態就好了
線程模型
參考
概念
線程是CPU調度的最小單位,可以獨立的完成任務;進程是資源擁有的基本單位。
在同一進程中,線程的切換不會引起進程切換。
在不同進程中進行線程切換,如從一個進程內的線程切換到另一個進程中的線程時,會引起進程切換
根據操作系統內核是否對線程可感知,可以把線程分為內核線程和用戶線程。
而操作系統中想要實現多線程,主要使用3種多線程模型:
● 內核線程模型
● 用戶線程模型
● 混合線程模型
內核線程模型
Kernel-Level Thread 簡稱KLT,內核線程模型完全依賴於操作系統內核,內核保存線程的狀態和信息,線程的創建、調度和管理由內核完成,並且系統內核負責將多個線程執行的任務映射到各個CPU中去執行。
線程管理的所有工作由內核完成,應用程序沒有進行線程管理的代碼,只有一個到內核級線程的編程接口. 內核為進程及其內部的每個線程維護上下文信息,調度也是在內核基於線程架構的基礎上完成。每個用戶線程都直接與一個內核線程相關聯
內核線程的優點:
- 多處理器系統中,內核能夠並行執行同一進程內的多個線程
- 如果進程中的一個線程被阻塞,能夠切換同一進程內的其他線程繼續執行(用戶級線程的一個缺點)
- 所有能夠阻塞線程的調用都以系統調用的形式實現,代價可觀
內核線程的缺點:
各種線程的操作都需要在用戶態和內核態之間頻繁切換,消耗太大,速度相對用戶線程模型來說要慢。
用戶線程模型
User-Level Thread 簡稱ULT,用戶線程模型不依賴操作系統核心,應用提供創建、同步、調度和管理線程函數來控制用戶線程。不需要線程從用戶態到內核態切換,速度快。
用戶級線程僅存在於用戶空間中,此類線程的創建、撤銷、線程之間的同步與通信功能,都無須利用系統調用來實現。用戶進程利用線程庫來控制用戶線程(如JAVA調用PThread庫)。用戶級線程是一種”多對一”的線程映射
優點:線程的各種操作以及切換消耗很低;
缺點:線程的所有操作都需要在用戶態實現,線程的調度實現起來異常復雜,並且系統內核對ULT無感知,如果線程阻塞則會引起整個進程的阻塞。
組合線程模型
組合線程模型是內核線程和用戶線程的混合使用,用戶線程仍然是在用戶態中創建,用戶線程的創建、切換和銷毀的消耗很低,用戶線程的數量不受限制。而LWP在用戶線程和內核線程之間充當橋梁,就可以使用操作系統提供的線程調度和處理器映射功能。