【unix网络编程】pthread_detach的意义与thread简单理解


前言


一、线程不join的结果

在主线程退出时,会调用exit导致线程退出,所有的子线程都会被停止执行。不管这个线程当前的属性是joinable还是detached。

二、等待子线程执行完毕的几种情况

1.阻塞主线程

#include "stdio.h"
#include "pthread.h"
#include "unistd.h"
#include "string.h"
#include "stdlib.h"
#define MAX_STRING_NUM 15
#define PUT_TO_STDOUT(a) write(fileno(stdout),a, strlen(a))
void *echo2terminal(void *data){
    //pthread_detach(pthread_self());
    sleep(3);
    char dest[1024];
    strcpy(dest, "this is echo:");
    strcat(dest, data);
    strcat(dest, "\n");
    write(fileno(stdout), dest, strlen(dest));
    return NULL;
}


int main(){
    pthread_t t;
    char *strings[MAX_STRING_NUM] = {
            "cccc", "java", "c++", "python", "JS",
            "1cccc", "1java", "1c++", "1python", "1JS",
            "2cccc", "2java", "2c++", "2python", "2JS",
    };
    for(int i=0;i<MAX_STRING_NUM;i++){
        PUT_TO_STDOUT(strings[i]);
        if(pthread_create(&t, NULL, echo2terminal, (void *)strings[i])){
            exit(1);
        }
        PUT_TO_STDOUT("ok\n");// write是系统调用,所以不用行缓冲直接出来
    }
    while (1){}
    return 0;

在这个程序里,如果不加入其中的while死循环,主进程就会可能在子进程结束前结束(子线程的函数sleep了3s),导致子线程中的内容无法打印。但是这种办法有个坏处,它无法释放子线程占有的某些资源(类似子进程退出时也无法自行释放其某些属性),所以要用join在主线程进行回收。

2.使用pthread_join

代码如下(示例):

#include "stdio.h"
#include "pthread.h"
#include "unistd.h"
#include "string.h"
#include "stdlib.h"
#define MAX_STRING_NUM 15
#define PUT_TO_STDOUT(a) write(fileno(stdout),a, strlen(a))
void *echo2terminal(void *data){
    //pthread_detach(pthread_self());
    sleep(3);
    char dest[1024];
    strcpy(dest, "this is echo:");
    strcat(dest, data);
    strcat(dest, "\n");
    write(fileno(stdout), dest, strlen(dest));
    return NULL;
}


int main(){
    pthread_t t[15];
    char *strings[MAX_STRING_NUM] = {
            "cccc", "java", "c++", "python", "JS",
            "1cccc", "1java", "1c++", "1python", "1JS",
            "2cccc", "2java", "2c++", "2python", "2JS",
    };
    for(int i=0;i<MAX_STRING_NUM;i++){
        PUT_TO_STDOUT(strings[i]);
        if(pthread_create(&t[i], NULL, echo2terminal, (void *)strings[i])){
            exit(1);
        }
        PUT_TO_STDOUT("ok\n");// write是系统调用,所以不用行缓冲直接出来
    }
    for (int i = 0; i < MAX_STRING_NUM; ++i) {
        pthread_join(t[i], NULL);
    }
    return 0;
}

这样可以在主线程中等待子线程执行完毕,并把资源回收。


3.pthread_detach的作用

如果我们在监听一个listen套接字时,为每一个已连接套接字创建一个子线程,由于join是阻塞的,我们不可能调用join对其进行资源回收,此时要用到pthread_detach让子线程在执行完毕时自行回收资源。
如《UNIX网络编程卷一》541页,我们不可能在箭头处进行join。
在这里插入图片描述
我们用获取用户输入来模拟监听套接字。

#include "stdio.h"
#include "pthread.h"
#include "unistd.h"
#include "string.h"
#include "stdlib.h"
#define MAX_INPUT_NUM 100
#define PUT_TO_STDOUT(a) write(fileno(stdout),a, strlen(a))
void *echo2terminal(void *data){
    pthread_detach(pthread_self());
    sleep(3);
    char dest[1024];
    strcpy(dest, "this is echo:");
    strcat(dest, data);
    write(fileno(stdout), dest, strlen(dest));
    free(data);
    return NULL;
}

int main(){
    pthread_t t;
    for(;;){
        char * input = (char *)malloc(MAX_INPUT_NUM);
        read(fileno(stdin), input, MAX_INPUT_NUM);
        if(pthread_create(&t, NULL, echo2terminal, (void *)input)){
            exit(1);
        }
    }
    return 0;
}

write和printf

在测试以上代码时,出现了先执行printf后执行write但printf打印的内容却在write后边的情况。
这是因为printf是c语言的函数,它在输出时具有行缓冲,如果printf的内容没有换行符的时候是不会输出到命令行的,但是write是系统调用,会直接打印到命令行。

总结

  1. 主线程return会导致子线程不再执行。
  2. join可以回收子线程的残余资源。
  3. detach可以让创建出的子线程在结束时自己回收残余资源。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值