線程的概念
1、在進程中,進程承擔資源分配,而線程是調度的基本單位,線程在進程內部運行,那麼,什麼是線程呢?簡單來說一個線程是進程的一個順序執行流。同類的多個線程共享一塊內存空間和一組系統資源,線程本身有一個供程序執行時的堆棧。線程在切換時負荷小,因此,線程也被稱爲輕負荷進程。一個進程中可以包含多個線程。linux中線程又稱爲輕量級進程。
線程的特點:
我們已經知道進程主要是獨佔系統資源,獨享系統地址空間;而線程相反,可以共享系統資源,儘管線程相對於進程可以共享系統資源,但是,它也有自己獨有的,每個線程獨有它的硬件上下文信息和私有棧(各種臨時變量,不至於混亂);進程間通信需要藉助系統中你的通信機制在:匿名管道(pipe)、命名管道(fifo)、消息隊列、信號量和共享內存機制,這些通信機制將佔用大量的系統資源,特別是在進行少量數據傳遞時顯得過於龐大,而線程可以訪問進程所擁有的已打開文件、定時器、信號量機構等。由於同一個進程內的線程共享內存和文件,所以線程之間互相通信不必調用內核,因而佔用更少的系統資源。
進程與線程的比較:
1、用戶空間資源的對比:
每個進程在創建時額外申請了新的內存空間以及代碼段、數據段、bss段、堆、棧空間,並且初始化成父親地址空間的值(複製),父子進程在創建後不能互相訪問對方資源。
每個線程的創建時僅在用戶空間申請自己的棧空間,而與其他進程共享其他地址空間(代碼段、數據段、bss段和堆空間)。
2、內核空間資源對比:
我們知道,每個進程中的PCB中的mm_struct結構體來描述這個進程的地址空間,使用fork()創建的新進程與父進程的地址空間是分開的,而同一進程下創建的線程共享這一地址空間,在創建線程時,內核仍會創建一個新的pcb來標識這個線程,內核對於進程或線程的認識來源於pcb,一個進程如果不創建新的進程,可以說他是一個只有一個線程的進程,如果創建了額外的線程,原來的進程亦稱爲主線程。
線程不能脫離進程而獨立存在,進程是操作系統管理資源的基本單位,而線程是linux系統調度的基本單元。
創建線程:
函數pthread_create()用來創建一個新的線程:
extern int pthread_create(pthread_t* _newthread,const pthread_attr_t* attr,void*(start)(void),void*arg);
第一個參數:存儲線程ID,參數爲指向線程ID的指針,線程ID在某個進程中是唯一的,不同進程中線程ID可能相同。
第二個參數:設置進程屬性,一般設置爲空
第三個參數:線程運行的代碼起始地址,即在此線程中運行那段代碼。。。
第四個參數:運行函數的參數地址,如果需要傳多個參數,則需要使用一個包含這些參數的結構體地址。
線程創建此函數如果執行成功,返回0;失敗,返回非0值。
創建線程代碼:
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
void* pthread_run()
{
printf("process ID:%d\n,pthread ID:%lu\n",getpid(),pthread_self());
sleep(3);
return (void*)5;
}
int main()
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&pthread_run,NULL);
printf("pcrcess ID:%d\n ,the ID:%lu\n",getpid(),pthread_self());
pthread_join(thread_id,NULL);
return 0;
}
運行結果:
運行結果發現:屬於同一個進程中不同線程。
線程退出與等待:
線程退出操作
a.使用return 退出,注意:不能用return 退出主線程;
b.使用pthread_exit()函數退出;
extern void pthread_exit(void* _retval);參數_retval爲退出碼
c.pthread_cancel函數取消該線程,線程也可自己取消自己;
退出代碼:
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
void* pthread_run()
{
printf("process ID:%d\n,pthread ID:%lu\n",getpid(),pthread_self());
sleep(200);
return (void*)5;
}
int main()
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&pthread_run,NULL);
printf("pcrcess ID:%d\n ,the ID:%lu\n",getpid(),pthread_self());
pthread_cancel(thread_id);
sleep(5);
pthread_join(thread_id,NULL);
return 0;
}
結果表明:代碼原來應該等待200s,但是取消新創建的線程後,5s代碼跑完。
線程的分離結合屬性:
在任何一個時間點上,線程是可結合的(joinable),或者是分離的(detached),線程分離的作用:當主線程與新線程無關時,主線程無需等待,提高效率。
如果要設置某個線程爲獨立線程,則可調用pthread_detach()函數;
函數聲明:extern int pthread_detach(pthread_t _th);
代碼:
#include<stdio.h>
#include<pthread.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
void* pthread_run()
{
printf("process ID:%d\n,pthread ID:%lu\n",getpid(),pthread_self());
sleep(200);
return (void*)5;
}
int main()
{
pthread_t thread_id;
pthread_create(&thread_id,NULL,&pthread_run,NULL);
printf("pcrcess ID:%d\n ,the ID:%lu\n",getpid(),pthread_self());
pthread_detach(thread_id);
sleep(5);
pthread_join(thread_id,NULL);
return 0;
}
同樣,代碼在5s時間內跑完,並且在代碼中沒有終止線程函數,說明創建的線程已經被分離。