惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 【当耐特】
云风的 BLOG
云风的 BLOG
罗磊的独立博客
C
Check Point Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Recent Announcements
Recent Announcements
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
爱范儿
爱范儿
I
InfoQ
Hugging Face - Blog
Hugging Face - Blog
T
Tailwind CSS Blog
B
Blog RSS Feed

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
pthread 中 join 和 detach|OhYee 博客
2020-03-03 · via OhYee 博客

对于 pthread 的 joinable 和 detached 两种线程模型进行对比

这是一篇最后编辑于 6 年前 的文章,其内容可能与目前实际情况差异较大,请注意甄别

pthread 的 joinable 和 detached

对于多线程程序,在程序开始运行后,会首先建立一个主线程,用于执行程序。在程序执行过程中,可能由于需要,会建立新的线程,用于执行并行操作。这时建立的线程称为子线程。
除去主线程外,其他所有的线程都属于子线程,为平等关系,即使是由子线程建立的子线程。

在 POSIX Threads 中,有两种线程类型:

  • 结合(joinable):对于结合的线程,主线程需要用join()函数来等待子线程执行完毕获得返回值,并释放资源;
  • 分离(detached):分离的线程相对而言独立于主线程,不需要主线程等待,会自动释放资源;joinable 的线程可以转换成 detached 的线程,但不能反向转换;

尽管一些文章会提到 joinable 线程在除非关机或重启都不会释放资源1,但是对于目前的操作系统的智能程度,在进程结束后都会被清除资源2,joinable 线程和 detached 线程的区别在于:

  • 主线程是否需要等待线程执行结束
  • 是否需要立即释放资源

一个更为直观的类比是,joinable 是类似于常见的 Python 线程模型,创建后开启线程,并且使用 join 来等待所有线程执行完成。当然,如果主线程不需要等待子线程执行结束就可以执行其他任务,也可以不使用 join 。这时效果上类似于 detached 线程模型3

而 detached 线程模型则很类似于 Go 语言的 goroutine 。子线程执行后,主线程就不再管子线程的事情,完全由子线程自行处理调度问题。(当然, Go 中可以使用 selectchannel 来实现等待任务执行结束,或者任务之间数据交互)

joinable 线程样例

执行下面的程序,会开启 THREAD_NUM 个线程,并在主线程等待其执行完毕

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

#define THREAD_NUM 3

void *thread_function(void *arg) {
    int tid = *(int *)arg;
    for (int i = 0; i < 3; i++) {
        printf("%d-%d\n", tid, i);
        sleep(1);
    }
    return NULL;
}

int main(void) {
    pthread_t *threads = malloc(THREAD_NUM * sizeof(pthread_t));

    for (int i = 0; i < THREAD_NUM; ++i) {
        if (pthread_create(&threads[i], NULL, thread_function, &i)) {
            printf("error creating thread.");
            abort();
        }
    }

    for (int i = 0; i < THREAD_NUM; ++i) {
        if (pthread_join(threads[i], NULL)) {
            printf("error join thread.");
            abort();
        }
    }

    printf("thread done! \n");
    return 0;
}

detached 线程样例

执行下面的程序,会开启 THREAD_NUM 个线程,并在主线程等待 2 秒(因为子线程需要 3 秒才能输出完毕,因此不会输出所有内容。

detached 线程很适合主线程在无限循环或者在运行很长的服务,同时有很多个需要并行执行的任务(一般不需要将执行信息反馈到创建的线程,当然也可以使用互斥锁等方法来在线程间同步数据)

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

#define THREAD_NUM 3

void *thread_function(void *arg) {
    int tid = *(int *)arg;
    for (int i = 0; i < 3; i++) {
        printf("%d-%d\n", tid, i);
        sleep(1);
    }
    return NULL;
}

int main(void) {
    pthread_t *threads = malloc(THREAD_NUM * sizeof(pthread_t));

    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    for (int i = 0; i < THREAD_NUM; ++i) {
        if (pthread_create(&threads[i], &attr, thread_function, &i)) {
            printf("error creating thread.");
            abort();
        }
    }

    sleep(2);

    printf("thread done! \n");
    exit(0);
}

参考资料


  1. c++11中thread join和detach的区别 ↩︎

  2. Detached vs. Joinable POSIX threads ↩︎

  3. python threading 一定要 join 吗? ↩︎