欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux線程之線程的創(chuàng)建、屬性、回收、退出、取消方式

 更新時間:2025年07月11日 14:32:40   作者:偉大的馬師兄  
文章總結(jié)了線程管理核心知識:線程號唯一、創(chuàng)建方式、屬性設(shè)置(如分離狀態(tài)與棧大小)、回收機制(join/detach)、退出方法(返回/pthread_exit/取消)及注意事項,如避免僵尸線程、內(nèi)存釋放、信號機制使用限制等

1. 線程號

進程號在系統(tǒng)中唯一,但線程號只在其所屬進程環(huán)境中有效。

(1)pthread_self函數(shù)

#include<pthread.h>

pthread_t pthread_self(void);
/*
功能:
    獲取線程號
返回值:
    調(diào)用此函數(shù)線程的ID
*/

pthread_self示例:

#include<stdio.h>
#include<pthread.h>

int main(int argc, const char* argv[]) {
    pthread_t tid = 0;
    tid = pthread_self();
    printf("當前線程id:%lu.\n", tid);
    return 0;
}

編譯時需要加上-pthread鏈接到pthread庫

運行結(jié)果:

(2)pthread_equal函數(shù)

int pthraed_equal(pthread_t t1, pthread_t t2);
/*
功能:
    判斷線程號t1、t2是否相等。
返回值:
    相等:非0
    不等:0
*/

pthread_equal示例:

#include<stdio.h>
#include<pthread.h>

int main(int argc, const char* argv[]) {
    pthread_t tid = 0;
    tid = pthread_self();

    if (pthread_equal(tid, pthread_self())) {
        printf("線程id相等.\n");
    } else {
        printf("線程id不等.\n");
    }
    return 0;
}

運行結(jié)果:

2. 線程的創(chuàng)建

pthread_create函數(shù)

#include<pthread.h>

int pthread_create(pthread_t* thread, const pthread_attr_t* attr, 
                    void* (*start_coutine)(void*), void* arg);
/*
功能:
    創(chuàng)建一個線程。
參數(shù):
    thread:線程id地址,為傳出參數(shù);
    attr:線程屬性結(jié)構(gòu)體,通常設(shè)置為NULL;
    start_routine:線程函數(shù)入口地址
    arg:傳給線程函數(shù)的參數(shù);
返回值:
    成功:0
    失?。悍?,未設(shè)置errno,不可使用perror。
*/

pthread_create示例:

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>

void* threadFunc(void* arg) { // 線程調(diào)度函數(shù)
    int var = (int)(long)(arg);
    printf("被創(chuàng)建線程id:%lu,傳過來的參數(shù):%d\n", pthread_self(), var);
    return NULL;
}

int main(int argc, const char* argv[]) {

    pthread_t tid;
    int ret = -1;

    // 初始化tid。因為不是所有系統(tǒng)中的pthread_t都是unsigned int, 因此最好使用memset初始化。
    memset(&tid, 0, sizeof(tid));

    // 創(chuàng)建線程
    ret = pthread_create(&tid, NULL, threadFunc, (void*)0x3);
    if (0 != ret) {
        printf("線程創(chuàng)建失??!\n");
        return 1;
    }
    printf("按下任意鍵繼續(xù)...\n");
    getchar();
    printf("主線程id:%lu\n", pthread_self());

    return 0;
}

運行結(jié)果:

3. 線程屬性

typedef struct {
    int etachstate;   // 線程的分離狀態(tài)
    int schedpolicy;  // 線程的調(diào)度策略
    struct sched_param schedparam; // 線程的調(diào)度參數(shù)
    int inheritsched;  // 線程的繼承性
    int scope;         // 線程的作用域
    size_t guardsize;  // 線程棧末尾的警戒緩沖區(qū)大小
    int stackaddr_set; // 線程棧的設(shè)置
    void* stackaddr;   // 線程棧的位置
    size_t stacksize;  // 線程棧的大小
} pthread_attr_t;
/*
功能:
    線程屬性結(jié)構(gòu)體;
主要成員:
    etachstate:線程的分離狀態(tài)
    guardsize:線程棧末尾的警戒緩沖區(qū)大小
    stackaddr:線程棧的位置
    stacksize:線程棧的大小

注意:
    線程屬性值不能直接設(shè)置,需使用相關(guān)函數(shù)進行操作。
    如pthread_create之前用pthread_attr_init初始化,
    之后用pthread_attr_destory釋放資源。
*/

(1)線程屬性的初始化和銷毀

#include<pthread.h>

int pthread_attr_init(pthread_attr_t* attr);
/*
功能:
    初始化線程屬性attr。
參數(shù):
    attr:待初始化的線程屬性結(jié)構(gòu)體。
返回值:
    成功:0
    失?。哄e誤碼
*/

int pthread_attr_destory(pthread_attr_t* attr);/*
功能:
    銷毀線程屬性attr。
參數(shù):
    attr:線程屬性結(jié)構(gòu)體。
返回值:
    成功:0
    失敗:非0錯誤碼
*/

(2)線程分離狀態(tài)屬性設(shè)置

  • 線程分離狀態(tài):無需其他線程阻塞等待線程結(jié)束以回收已結(jié)束線程的資源,而是讓內(nèi)核回收已結(jié)束線程的資源。
  • 線程非分離狀態(tài):某個線程(如主線程)阻塞等待子線程結(jié)束以回收其資源。
#include<pthread.h>

int pthread_attr_setdetachstate(pthread_attr_t* attr, int detachstate);
/*
功能:
    設(shè)置線程屬性為分離。
參數(shù):
    attr:已初始化的線程屬性結(jié)構(gòu)體;
    detachstate:是否分離:
        PTHREAD_CREATE_DETACHED:分離
        PTHREAD_CREATE_JOINABLE:非分離
返回值:
    成功:0
    失?。悍?
*/

int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate);
/*
功能:
    獲取線程是否分離狀態(tài)
參數(shù):
    attr:線程屬性結(jié)構(gòu)體。
        detachstate:是否分離:
        PTHREAD_CREATE_DETACHED:分離
        PTHREAD_CREATE_JOINABLE:非分離
返回值:
    成功:0
    失?。悍?錯誤碼
*/

線程設(shè)置分離屬性示例

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>

void* func(void* arg) {
    printf("子線程開始...\n");
    sleep(2);
    printf("子線程結(jié)束...\n");
    pthread_exit(NULL);
}

int main(int argc, const char* argv[]) {

    int ret = -1;
    pthread_t tid = -1;
    pthread_attr_t attr;

    // 初始化線程屬性
    ret = pthread_attr_init(&attr);
    if (0 != ret) {
        printf("線程屬性初始化失敗。\n");
        return 1;
    }

    // 設(shè)置線程屬性為分離狀態(tài)
    ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if (0 != ret) {
        printf("線程分離屬性設(shè)置失敗。\n");
        return 1;
    }

    // 創(chuàng)建線程
    ret = pthread_create(&tid, &attr, func, NULL);
    if (0 != ret) {
        printf("線程創(chuàng)建失敗.\n");
        return 1;
    }

    sleep(3);

    // join看看是否為分離狀態(tài)
    ret = pthread_join(tid, NULL);
    if (0 != ret) {
        printf("線程為分離狀態(tài),無需join.\n");
    } else {
        printf("線程為非分離狀態(tài),已被join.\n");
    }

    // 銷毀線程屬性
    ret = pthread_attr_destroy(&attr);
    if (0 != ret) {
        printf("線程屬性銷毀失敗。\n");
        return 1;
    }

    return 0;
}

運行結(jié)果:

(3)線程棧大小獲取和設(shè)置

#include<pthread.h>

int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize);
/*
功能:
    設(shè)置線程棧大小。
參數(shù):
    attr:線程屬性結(jié)構(gòu)體;
    stacksize:線程棧大??;
返回值:
    成功:0;
    失敗:錯誤碼
*/

int pthread_attr_getstacksize(const pthread_attr_t* attr, size_t* stacksize);
/*
功能:
    獲取線程棧大小。
參數(shù):
    attr:線程屬性結(jié)構(gòu)體指針;
    stacksize:返回的線程棧大??;
返回值:
    成功:0;
    失?。悍?錯誤碼
*/

4. 線程的回收

(1)pthread_join函數(shù)

主線程回收線程資源,會阻塞。

#include<pthread.h>

int pthread_join(pthread_t thread, void** retval);
/*
功能:
    類似于wait()函數(shù)。等待線程thread結(jié)束,回收線程資源;若線程已結(jié)束,則會立即返回。
參數(shù):
    thread:等待回收的線程號;
    retval:存儲進程退出狀態(tài)的指針的地址;
返回值:
    成功:0
    失?。悍?錯誤碼
*/

pthread_join示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pthread.h>
#include<unistd.h>

void* func() {
    printf("子線程開始執(zhí)行...\n");
    sleep(3);
    printf("子線程結(jié)束執(zhí)行...\n");
    return (void*)0x3;
}

int main(int argc, const char* argv[]) {

    pthread_t tid;
    int ret = -1;
    void* retp = NULL;

    memset(&tid, 0, sizeof(tid));

    // 創(chuàng)建線程
    ret = pthread_create(&tid, NULL, func, NULL);
    if (0 != ret) {
        printf("線程創(chuàng)建失敗.\n");
        return 1;
    }

    printf("主線程執(zhí)行...\n");

    // 等待線程結(jié)束 pthread_join會阻塞
    ret = pthread_join(tid, &retp);
    if (0 != ret) {
        printf("線程join失敗.\n");
        return 1;
    }

    printf("retp: %p\n", retp);
    printf("主線程退出...\n");

    return 0;
}

運行結(jié)果:

(2)pthread_detach函數(shù)

內(nèi)核回收線程資源,不會阻塞。

#include<pthread.h>

int pthread_detach(pthread_t thread);
/*
功能:
    使線程thread與當前進程分離,之后線程結(jié)束后的資源回收由內(nèi)核完成,因此不會阻塞。
參數(shù):
    thread:線程號;
返回值:
    成功:0
    失?。悍?
*/

 pthread_detach示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>

void* func(void* arg) {
    printf("子線程開始...\n");
    for (int i = 0; i < 3;++i) {
        sleep(1);
        printf("子線程工作%ds\n", i);
    }
    printf("子線程結(jié)束...\n");
    return NULL;
}

int main(int argc, const char* argv[]) {

    int ret = -1;
    pthread_t tid = -1;

    // 創(chuàng)建線程
    ret = pthread_create(&tid, NULL, func, NULL);
    if (0 != ret) {
        printf("線程創(chuàng)建失敗.\n");
        return 1;
    }

    // 設(shè)置線程分離
    ret = pthread_detach(tid);
    if (0 != ret) {
        printf("線程分離失敗.\n");
        return 1;
    }

    printf("主線程:按回車鍵退出..\n");
    getchar();

    return 0;
}

運行結(jié)果:

線程設(shè)置為detach狀態(tài),主線程不必阻塞等待回收子線程資源,而是由內(nèi)核完成。

5. 線程的退出

若在線程中用exit函數(shù)退出,則導致整個進程退出,而非退出這一個線程。

如下三者可在不結(jié)束整個進程的情況下結(jié)束線程:

a)線程從執(zhí)行函數(shù)中返回;

b)線程調(diào)用pthread_exit退出線程;

c)線程被同一進程中的其它線程取消。

pthread_exit函數(shù)

#include<pthread.h>

void pthread_exit(void* retval);
/*
功能:
    退出調(diào)用線程。
參數(shù):
    retval:存儲線程退出狀態(tài)的指針。
*/

6. 線程的取消

pthread_cancel函數(shù)

#include<pthread.h>

int pthread_cancel(pthread_t thread);
/*
功能:
    殺死線程thread;
參數(shù):
    thread:目標線程ID;
返回值:
    成功:0
    失?。悍?錯誤碼。
*/

pthread_cancel示例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>

void* func(void* arg) {
    printf("子線程開始...\n");
    for (int i = 0; i < 5;++i) {
        sleep(1);
        printf("子線程工作%ds\n", i);
    }
    printf("子線程結(jié)束...\n");
    pthread_exit(NULL);
}

int main(int argc, const char* argv[]) {

    int ret = -1;
    pthread_t tid = -1;

    // 創(chuàng)建線程
    ret = pthread_create(&tid, NULL, func, NULL);
    if (0 != ret) {
        printf("線程創(chuàng)建失敗.\n");
        return 1;
    }

    // 設(shè)置線程分離
    ret = pthread_detach(tid);
    if (0 != ret) {
        printf("線程分離失敗.\n");
        return 1;
    }

    sleep(3);
    pthread_cancel(tid);  // 殺死線程

    printf("主線程:按回車鍵退出..\n");
    getchar();

    return 0;
}

運行結(jié)果:

7. 線程使用注意事項

(1)主線程退出,而其余線程不退出,主線程應(yīng)調(diào)用pthread_exit

(2)避免僵尸線程方式:

  • a)pthread_join;
  • b)pthread_detach;
  • c)pthread_create前設(shè)置線程分離屬性;

(3)malloc和mmap申請的內(nèi)存可被其他線程釋放;

(4)避免在多線程中fork,除非馬上使用exec;

(5)避免多線程中使用信號機制。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論