程序
在了解線程之前,首先需要了解UNIX/Linux程序。 程序是由作業系統建立的,需要相當數量的“開銷”。 程序包含有關程式資源和程式執行狀态的資訊,包括:它是一個在随機通路記憶體(RAM)中,正在執行的程式,它是資源配置設定的最小機關。
1)程序ID,程序組ID,使用者ID群組ID
2)環境
3)工作目錄
4)程式說明
5)寄存器
6)棧
7)堆
8)檔案描述符
9)信号動作
10)共享庫
11)程序間通信工具(例如消息隊列,管道,信号量或共享記憶體)
process.gif
線程
它是程式執行的最小機關,又稱為輕量級的程序,作業系統獨立排程和分派到CPU的基本機關,它是程序中的一個實體,一個程序中可以包含多個線程。這些線程共享同一個程序中的資源,我們之前以程序為機關的程式設計模式,也叫單線程的程式設計模式
ss1.png
存在于流程中并使用流程資源
隻要其父程序存在并且作業系統支援它,便擁有自己的獨立控制流
僅複制需要獨立計劃的必要資源
可以與平等(獨立)運作的其他線程共享程序資源
如果父程序死亡-或類似的事物死亡
是“輕量級的”,因為大多數開銷已經通過建立其過程來完成。
并發:在同一個核心的CPU中,同一個時刻,隻能有一條指令執行,但多個程序指令被快速輪換執行,使得在宏觀上具有多個程序同時執行的效果。
ss17.png
并行:是指在同一個時刻,有多條指令在多個處理器上同時執行。
同步:彼此有依賴關系的調用不應“同時發生”,而同步就是阻止同時發生的事情
異步:和同步的概念是相對的,任何兩個彼此獨立的操作是異步的,它表明事件是獨立發生的。
建立一個線程
首先每個線程,作業系統都會給每個線程配置設定一個線程ID,在Linux下,程序ID是一個pid_t類型的整數,線程ID是一個辨別符類型pthread_t的整數
ss18.png
像pthread_self()和getpid()這些函數在安裝Linux/Unix系統後原生内置的函數,通常叫系統調用(Syscall),就是系統原生提供給C/C++程式員使用的系統函數接口,這些系統函數通常可以通過man指令能夠查到它的使用方法,例如可以在/usr/include目錄下檢視對應的系統函數的頭檔案
vim /usr/include/bits/pthreadtypes.h
我們知道,線程ID其實就是一個long int的無符号整數
ss18.png
我們也可以通過man getpid和man pthread_self分别檢視一下,在使用它們之前需要導入那些依賴的頭檔案,如果你不熟悉的系統函數,你應該經常通過man指令來檢視對應的描述文檔。
2019-12-31 09-41-51螢幕截圖.png
程式設計示例
我們在沒有提及多線程程式設計模式的時,那些編寫的示例代碼都是單線程的程式,也就是一個程序中隻有一個線程。我們下面的例子是要擷取目前運作程序的ID和線程ID,該示例就是一個單線程的程式。
#include
#include
#include
#include
#include
int main(void){
pid_t pid=getpid();
pthread_t tid=pthread_self();
printf("目前線程ID:%lx,程序ID:%u\n",tid,pid);
return 0;
}
在編譯多線程的程式時,記得連結pthread庫,即
gcc app.c -o app -pthread
輸出
目前線程ID:7fedbcb524c0,程序ID:30167
小結:
程序是擷取資源的最小機關,例如組成我們程序的函數棧和堆記憶體,注意在主流系統中每個程序中有它對應的函數棧和堆記憶體,而且這些堆和棧對用于它們的程序來說是私有的,其他程序無法通路。
線程是程序中的一個或多個執行個體,而線程的職責是消耗程序獲得的系統資源(CPU中的寄存器,計算單元和控制單元,以及随機通路記憶體),在一個程序中,隻有一個線程的程式,該線程也叫主線程,主線程可以建立其他子線程。