一、什麼是線程?
線程是在進程內部運行的控制流程。多線程的控制流程可以長期共存,操作系統會在各線程之間調度和切換,就像在多個進程之間調度和切換一樣。
由於同一個進程的多個線程共享同一地址空間地址空間,因此代碼段和數據段都是共享的,如果定義一個函數,在各線程之中都可以調用,如果定義一個全局變量,在各線程中都可以訪問到的,除此之外,線程還共享以下資源:
1>文件描述符表
2>每種信號的處理方式
3>當前工作目錄
4>用戶id和組id
5>堆空間
但是有些資源是每個線程獨自有一份的
1>線程id
2>上下文,包括各種寄存器的值、程序計數器和棧指針
3>棧空間
4>errno變量
5>信號屏蔽字
6>調度優先級
二、線程與進程的區別
進程是程序執行時的一個實例,即它是程序已經執行到課中程度的數據結構的彙集。從內核的觀點看,進程的目的就是擔當分配系統資源(CPU時間、內存等)的基本單位。
線程是進程的一個執行流,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。一個進程由幾個線程組成(擁有很多相對獨立的執行流的用戶程序共享應用程序的大部分數據結構),線程與同屬一個進程的其他的線程共享進程所擁有的全部資源。
進程——資源分配的最小單位,線程——程序執行的最小單位
進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。線程有自己的堆棧和局部變量,但線程沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。
總的來說就是:進程有獨立的地址空間,線程沒有單獨的地址空間(同一進程內的線程共享進程的地址空間)。
三、下面是線程的簡單代碼
線程創建
/*Makefile*/
thread:thread.c
gcc -o $@ $^ -lpthread
.PHONY:clean
clean:
rm -f thread
/*thread.c*/
/*************************************************************************
> File Name: thread.c
> Author:LordWingF
> Mail: NULL
> Created Time: Sun 04 Jun 2017 04:10:21 AM PDT
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
//創建新線程
void* thread_run(void* arg)
{
printf("new thread, thread is : %u pid : %d\n", pthread_self(), getpid());
sleep(5);
/*退出方式*/
pthread_exit((void*)123);
//finish thread 線程專用
//exit(123);
//finish process, not thread 進程專用
//return (void*)1;
//could finish process, thread too 線程進程都可以使用
}
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, thread_run, NULL);
sleep(1);
/*pthread_cancel(pthread_t thread)發送終止信號給thread線程,如果成功則返回0,否則爲非0值*/
pthread_cancel(tid);
while(1){
printf("main thread, thread is : %u pid : %d\n", pthread_self(), getpid());
sleep(1);
}
return 0;
}
程序運行如下
再調用ps -ef -f | grep proftpd 來查看創建的線程
線程的等待釋放
/*Makefile*/
thread:thread.c
gcc -o $@ $^ -lpthread
.PHONY:clean
clean:
rm -f thread
/*thread.c*/
/*************************************************************************
> File Name: thread.c
> Author:LordWingF
> Mail: NULL
> Created Time: Sun 04 Jun 2017 04:10:21 AM PDT
************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
//創建新線程
void* thread_run(void* _val)
{
/*如果一個線程結束運行但沒有被join,則它的狀態類似於進程中的殭屍進程,這時可以在子線程中加入代碼pthread_detach(pthread_self())或者父線程調用pthread_detach(thread_id)*/
pthread_detach(pthread_self());
printf("%s\n",(char*)_val);
return NULL;
}
/*主線程*/
int main()
{
//創建新線程
pthread_t tid;
int tret = pthread_create(&tid, NULL, thread_run, "new thread run");
//定義ret接受新線程的返回值,如果ret不是0的話,則說明等待失敗,反之,等待成功。在這裏因爲子線程中調用了pthread_detach(pthread_self()),所以一定會返回失敗
sleep(1);
void* ret;
if(pthread_join(tid, &ret) != 0){
printf("join fail\n");
}
}
程序運行如下
這就是線程的簡單創建和退出等待