線程初識

線程的概念

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);  //wait
    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);
    //pthread_cancel(thread_id);
    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);  //wait
    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_cancel(thread_id);
    pthread_detach(thread_id);
    sleep(5);
    pthread_join(thread_id,NULL);  //wait
    return 0;
}

這裏寫圖片描述

同樣,代碼在5s時間內跑完,並且在代碼中沒有終止線程函數,說明創建的線程已經被分離。

發佈了71 篇原創文章 · 獲贊 62 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章