天天看點

Linux線程總結---線程的建立、退出、取消、回收、分離屬性

一、線程的基本概念

1、基本概念
	線程是特殊的程序,在作業系統中,線程不能獨立存在,線程是程序建立出來的,一個程序可以有多個線程,程序退出了,線程也會跟着退出。
	2、資源
	每個程序都有自己獨立的堆、棧、資料段、代碼段等空間,線程基本沒有獨立的資源,隻有必不可少的資源(棧),同一程序之間的線程共享程序中的所有資源。
           

二、線程相關的API

1、線程建立函數

Linux線程總結---線程的建立、退出、取消、回收、分離屬性

thread:存放線程的id

attr:線程的分離屬性—>NULL

start_routine :參數為void *, 傳回值也是void * 類型的函數指針。(線程執行函數)

arg:函數的參數

傳回值:成功傳回0,失敗傳回非0.

代碼段:

void * Pthread_Task(void *arg)// arg = data;
{
	int a = (long)arg;
	printf("-----%d\n", a);
}
int main()
{
    long data = 110;
    //建立線程
	pthread_t pid;
	int ret = pthread_create(&pid, NULL, Pthread_Task, (void *)data);
	if(ret != 0)
	{
		perror("ptread_create");
		return -1;
	}
	else
	{
		printf("線程建立成功!\n");
	}
}
           

2、線程的退出

Linux線程總結---線程的建立、退出、取消、回收、分離屬性

retal: 傳回線程結束的狀态(void*變量)

讓線程退出的三種方法:

  • 線程的任務函數調用完傳回退出(直接死),讓其他人給這個死的線程回收線程資源.線程調用這個pthread_exit();

    立馬死了,讓其他人給這個死的線程回收線程資源.

  • 取消線程 pthreada_cancel:隻是一個請求(不能保證線程肯定會去退出)
  • 設定線程位分離屬性,他死了不需要别人給他收屍。

    3、線程資源回收函數

    Linux線程總結---線程的建立、退出、取消、回收、分離屬性

    thread: 子線程的id

    retval: 子線程結束狀态

    等待回收子線程的資源(棧空間),作用相當于子線程中的waitpid

    pthread_join:預設是堵塞的,自己不能調用pthread_join來回收自己。

    4、設定線程分離屬性

    Linux線程總結---線程的建立、退出、取消、回收、分離屬性

    1)分離屬性:子線程的資源由系統回收,線程的資源回收需使用pthread_join來實作,如果該線程運作沒有結束,會阻塞主線程,當主線程還要建立新線程來做一些事情,此時主線程就會因為調用pthread_join而被堵塞,就沒辦法處理其他事務,是以引入線程的分離屬性,他不需要主線程回收,在退出系統會自動回收。

    線程分離函數:

    int pthread_detach(pthread_t thread);

    thread:線程id

    2)線程建立時選擇分離屬性-----對pthread_create的第二個參數進行設定

    pthread_attr_t *attr

    定義一個pthread_attr_t 類型變量attr,然後對這個變量attr 進行初始化 pthread_attr_init()最後設定分離屬性。

    ① 初始化線程屬性

    int pthread_attr_init(pthread_attr_t *attr);

    ② 設定分離屬性

    int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

    5、線程的取消

    Linux線程總結---線程的建立、退出、取消、回收、分離屬性
    Linux線程總結---線程的建立、退出、取消、回收、分離屬性
    Linux線程總結---線程的建立、退出、取消、回收、分離屬性

    1)線程取消函數:pthread_cancel()

    2)設定線程取消響應—>是否響應取消信号

    3)設定響應取消信号的類型---->立即響應、延時響應

    代碼段:

#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
struct Data
{
    char pthread_name[10];
};

void *Pthread_Task(void *arg)
{
    //設定線程取消狀态---接受取消請求
    int pthread_setcancelstate_ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
    if (pthread_setcancelstate_ret != 0)
    {
        perror("pthread_setcancelstate");
        exit(-1);
    }
    while (1)
    {
        struct Data *p = (struct Data *)arg;
        printf("%s\n", p->pthread_name);
        sleep(1);
    }
    pthread_exit(NULL);
}

int main()
{
    pthread_t pid;
    struct Data d1;
    memset(&d1, 0, sizeof(d1));
    strcpy(d1.pthread_name, "hello");
    //建立線程
    int ret = pthread_create(&pid, NULL, Pthread_Task, (void *)&d1);
    if (ret != 0)
    {
        perror("pthread_create");
        exit(-1);
    }
    printf("5s之後發送取消請求\n");
    sleep(5);
    //取消線程
    pthread_cancel(pid);
    pause();
    return 0;
}
           

壓棧和彈棧要配套使用,想讓誰響應注冊函數,那麼就是誰裡面寫壓棧和彈棧。

代碼段:

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

//線程注冊函數
void Pthread_At_Fun(void *arg)
{
    printf("%s\n", (char *)arg);
}
//線程任務函數
void *Pthread_Task(void *arg)
{   
    //壓棧
    pthread_cleanup_push(Pthread_At_Fun, (void *)"死亡閃現");
    printf("三秒之後我将死亡\n");
    sleep(3);
    pthread_exit(NULL);
    //彈棧
    pthread_cleanup_pop(0);  
}
int main()
{
    //建立線程
    pthread_t pid;
    int pthread_create_ret = pthread_create(&pid, NULL, Pthread_Task, NULL);
    if(pthread_create_ret != 0)
    {
        perror("pthread_create");
        exit(-1);
    }
    while(1)
    {
        printf("我看見小線程死亡閃現!\n");
        sleep(1);
    }
    return 0;
}
           

繼續閱讀