Linux:回收循環創建的多個線程


上午我說了循環創建多個線程,由於進程與線程是如此的相似,進程我們知道要回收,那么線程也自然要回收啦。我們接着看控制原語:

線程與共享

線程間共享全局變量!

牢記】:線程默認共享數據段、代碼段等地址空間,常用的是全局變量。而進程不共享全局變量,只能借助mmap。

pthread_exit函數

將單個線程退出

    void pthread_exit(void *retval);    參數:retval表示線程退出狀態,通常傳NULL

思考:使用exit將指定線程退出,可以嗎?                                            【pthrd_exit.c】

    結論:線程中,禁止使用exit函數,會導致進程內所有線程全部退出。

    在不添加sleep控制輸出順序的情況下。pthread_create在循環中,幾乎瞬間創建5個線程,但只有第1個線程有機會輸出(或者第2個也有,也可能沒有,取決於內核調度)如果第3個線程執行了exit,將整個進程退出了,所以全部線程退出了。

    所以,多線程環境中,應盡量少用,或者不使用exit函數,取而代之使用pthread_exit函數,將單個線程退出。任何線程里exit導致進程退出,其他線程未工作結束,主控線程退出時不能return或exit。

另注意,pthread_exit或者return返回的指針所指向的內存單元必須是全局的或者是用malloc分配的,不能在線程函數的棧上分配,因為當其它線程得到這個返回指針時線程函數已經退出了。

總結exit、return、pthread_exit各自退出效果。

return:返回到調用者那里去。

pthread_exit():將調用該函數的線程退出

exit: 將進程退出。

pthread_join函數

阻塞等待線程退出,獲取線程退出狀態        其作用,對應進程中 waitpid() 函數。

    int pthread_join(pthread_t thread, void **retval); 成功:0;失敗:錯誤號

    參數:thread:線程ID (【注意】:不是指針);retval:存儲線程結束狀態。

    對比記憶:

        進程中:main返回值、exit參數-->int;等待子進程結束 wait 函數參數-->int *

        線程中:線程主函數返回值、pthread_exit-->void *;等待線程結束 pthread_join 函數參數-->void **

參數 retval 非空用法。

調用該函數的線程將掛起等待,直到id為thread的線程終止。thread線程以不同的方法終止,通過pthread_join得到的終止狀態是不同的,總結如下:

  1. 如果thread線程通過return返回,retval所指向的單元里存放的是thread線程函數的返回值。
  2. 如果thread線程被別的線程調用pthread_cancel異常終止掉,retval所指向的單元里存放的是常數PTHREAD_CANCELED。
  3. 如果thread線程是自己調用pthread_exit終止的,retval所指向的單元存放的是傳給pthread_exit的參數。
  4. 如果對thread線程的終止狀態不感興趣,可以傳NULL給retval參數。

上面說的很清楚啦,所以回收線程的代碼實現也很簡單啦:

#include <stdio.h>

#include <pthread.h>

#include <string.h>

#include <stdlib.h>

typedef struct {

    int x;

    int y;

    char p[128];

}my_func;

void *func(void*arg)

{

    my_func *mf = (my_func*)malloc(sizeof(my_func));

    int i = (int)arg;

    mf->x = i;

    mf->y = i * i;

    strcpy(mf->p, "my lover is dandan.");

    printf("我是第%d個線程,我的線程ID是%lu\n", i + 1, pthread_self());

    pthread_exit(mf);

}

int main(void)

{

    pthread_t pth[5];

    my_func *mf;//這里是指針啊,是指針啊,不是一個實例啊

    for (int i = 0; i != 5; i++)

    {

        pthread_create((pth + i), NULL, func, (void*)i);

        if (!pthread_join(pth[i], (void**)&mf))

        {

            printf("回收線程成功!線程ID:%lu。\n", pth[i]);

            printf("my_func中的x = %d, y = %d, p = %s。\n\n", mf->x, mf->y, mf->p);

        }

        else

            printf("失敗!\n");

    }

    return 0;

}

主要是各種轉化要注意,還有的是:my_func *mf;//這里是指針啊,是指針啊,不是一個實例啊         這句話很重要啊,我就說為什么我的mf輸出像是沒有經過初始化和賦值操作的。還有,不用擔心我沒有free而造成內存泄漏,pthread_exit函數是把這些考慮好了的。還有我的pthread_exit是傳參數進去的,主要是想獲取一下線程退出的狀態。是不是和wait很類似?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM