当前位置: 首页 > news >正文

【pthread_detach/pthread_join】pthread_detach()与pthread_join的区别?

简洁

创建linux线程,创建后可以设置其为(与主线程)分离状态/结合状态。

简单来说:

 pthread_detach()即主线程与子线程分离,子线程结束后,资源自动回收。由系统自动释放

pthread_join()即是子线程合入主线程,主线程阻塞等待子线程结束,然后回收子线程资源。

详细


一、创建分离线程

有两种方式创建分离线程:

(1)在线程创建时将其属性设为分离状态(detached);

(2)在线程创建后将其属性设为分离的(detached)。

二、分离线程的作用

由系统来回收线程所占用资源。

三、实例

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>

void* thread1(void *arg)
{
    while (1)
    {
        usleep(100 * 1000);
        printf("thread1 running...!\n");
    }
    printf("Leave thread1!\n");

    return NULL;
}

int main(int argc, char** argv)
{
    pthread_t tid;

    pthread_create(&tid, NULL, (void*)thread1, NULL);
    pthread_detach(tid);  // 使线程处于分离状态
    sleep(1);
    printf("Leave main thread!\n");
    pthread_exit("end"); //这个地方执行后,子进程并没有退出
//    return 0; //return后,系统会调用_exit,所有进程都会退出。
}

#gcc a.c -lpthread

#./a.out
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
Leave main thread!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!

pthread_exit("end"); //这个地方执行后,子进程并没有退出
可以看出main线程退出后,thread_1并没有退出。

$ cat a.c
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>

void* thread1(void *arg)
{
    while (1)
    {
        usleep(100 * 1000);
        printf("thread1 running...!\n");
    }
    printf("Leave thread1!\n");

    return NULL;
}

int main(int argc, char** argv)
{
    pthread_t tid;

    pthread_create(&tid, NULL, (void*)thread1, NULL);
    pthread_detach(tid);  // 使线程处于分离状态
    sleep(1);
    printf("Leave main thread!\n");
    return 0; //return后,系统会调用_exit,所有进程都会退出。
}

$ ./a.out
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
Leave main thread!

 return 0; //return后,系统会调用_exit,所有进程都会退出。

可以看出main线程return后,子线程也退出了。

如果把pthread_deteach改为pthread_join,因为子线程是while(1)所以主线程也不会退出(因为只有子线程退出后 主线程才会执行pthread_join后面的代码)。

linjuntao@linjuntao:~/work/mt8516-p1v2/build/tmp/deploy/images/aud8516p1v2-slc-bluez$ cat a.c
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>

void* thread1(void *arg)
{
    while (1)
    {
        usleep(100 * 1000);
        printf("thread1 running...!\n");
    }
    printf("Leave thread1!\n");

    return NULL;
}

int main(int argc, char** argv)
{
    pthread_t tid;

    pthread_create(&tid, NULL, (void*)thread1, NULL);
    //pthread_detach(tid);  // 使线程处于分离状态
    pthread_join(tid,NULL);  //使线程处于结合状态
    sleep(1);
    printf("Leave main thread!\n");
    return 0;
}

linjuntao@linjuntao:~/work/mt8516-p1v2/build/tmp/deploy/images/aud8516p1v2-slc-bluez$ ./a.out
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!

这可以在main中使用pthread_cancel,明确退出子线程。

---------------------
原文:https://blog.csdn.net/linchuanzhi_886/article/details/80406608

调用pthread_join 后只有子线程退出后 主线程才会执行pthread_join后面的代码,用途:
如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到pthread_join()方法

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <dirent.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <time.h>

void* thread1(void *arg)
{ int i = 0;
    while (i++ < 5)
    {
        usleep(100 * 1000);
        printf("thread1 running...!\n");
    }
    printf("Leave thread1!\n");

    return NULL;
}

int main(int argc, char** argv)
{
    pthread_t tid;

    pthread_create(&tid, NULL, (void*)thread1, NULL);
    //pthread_detach(tid);  // 使线程处于分离状态
    pthread_join(tid,NULL);  //使线程处于结合状态
    sleep(1);
    printf("Leave main thread!\n");
    return 0;
}


thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
thread1 running...!
Leave thread1!
Leave main thread!


代码二:

#include "stdafx.h"
#include <pthread.h>
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "pthreadVC2.lib")
static int count = 0;
void* thread_run(void* parm)
{
    for (int i=0;i<5;i++)
    {
        count++;
        printf("The thread_run method count is = %d\n",count);
        Sleep(1000);
    }
    return NULL;
}
int main()
{
    pthread_t tid;
    pthread_create(&tid, NULL, thread_run,NULL);
    // 加入pthread_join后,主线程"main"会一直等待直到tid这个线程执行完毕自己才结束
    // 一般项目中需要子线程计算后的值就需要加join方法
    pthread_join(tid,NULL);
    // 如果没有join方法可以看看打印的顺序
    printf("The count is = %d\n",count);
    getchar();
    return 0;
}
---------------------
原文:https://blog.csdn.net/dinghqalex/article/details/42921931

加了pthread_join()方法的打印:

如果把里面的pthread_join()方法注释掉的打印:

------------------------------------------------------------------------------以下为以前的认知----------------------------

前言:
1.linux线程执行和windows不同,pthread有两种状态joinable状态和unjoinable状态,如果线程是joinable状态,当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程,这些资源在线程函数退出时或pthread_exit时自动会被释放
2.unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。或者将线程置为 joinable,然后适时调用pthread_join.
3.其实简单的说就是在线程函数头加上 pthread_detach(pthread_self())的话,线程状态改变,在函数尾部直接 pthread_exit线程就会自动退出。省去了给线程擦屁股的麻烦。
原文:https://blog.csdn.net/weibo1230123/article/details/81410241

简单来说:

 pthread_detach()即主线程与子线程分离,子线程结束后,资源自动回收。由系统自动释放

pthread_join()即是子线程合入主线程,主线程阻塞等待子线程结束,然后回收子线程资源。

【转】在任何一个时间点上,线程是可结合的(joinable)或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(例如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。

    默认情况下,线程被创建成可结合的。为了避免存储器泄漏,每个可结合线程都应该要么被显示地回收,即调用pthread_join;要么通过调用pthread_detach函数被分离。

[cpp]

int pthread_join(pthread_t tid, void**thread_return);  若成功则返回0,若出错则为非零。 

 线程通过调用pthread_join函数等待其他线程(调用者-母线程?)终止。pthread_join函数分阻塞,直到线程tid终止,将线程例程返回的(void*)指针赋值为thread_return指向的位置,然后回收已终止线程占用的所有存储器资源。

[cpp] int pthread_detach(pthread_t tid); 若成功则返回0,若出错则为非零。 

    pthread_detach用于分离可结合线程tid。线程能够通过以pthread_self()为参数的pthread_detach调用来分离它们自己。

    如果一个可结合线程结束运行但没有被join,则它的状态类似于进程中的Zombie Process,即还有一部分资源没有被回收,所以创建线程者应该调用pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源。

    由于调用pthread_join后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。例如,在Web服务器中当主线程为每个新来的连接请求创建一个子线程进行处理的时候,主线程并不希望因为调用pthread_join而阻塞(因为还要继续处理之后到来的连接请求),这时可以在子线程中加入代码

    pthread_detach(pthread_self())

或者父线程调用

    pthread_detach(thread_id)(非阻塞,可立即返回)

这将该子线程的状态设置为分离的(detached),如此一来,该线程运行结束后会自动释放所有资源。

相关文章:

  • 【时间复杂度】时间复杂度
  • 【Dll调试】DLL调试方法
  • 【机器学习】线性回归数学推导
  • 【VS消除警告】VS消除特定警告/安全函数警告C4996 strncpy unsafe……
  • CSDN 博客备份工具
  • 【FTP】linux FTP传文件到windows
  • 【VS】在VS中添加lib库的三种方法
  • 【合并lib】windows下多个lib合并的方法|查看lib是导入库还是静态库
  • 【python】anaconda 安装第三方包
  • 【IP/TCP】127.0.0.1和localhost和本机IP三者的区别
  • 【C/C++相互调用】C调用C++库和C++调用C库的方法
  • [STL]C++ STL中常见容器的时间复杂度
  • 【STL map】map用法、插入方法、pair和make_pair的区别
  • 【字符编码】 简洁理解ANSI,UTF8,Unicode,ASCII编码的差别
  • [MYSQL]mysql将两个表结果合并到一起
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • mockjs让前端开发独立于后端
  • spring cloud gateway 源码解析(4)跨域问题处理
  • Vim 折腾记
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 欢迎参加第二届中国游戏开发者大会
  • 基于 Babel 的 npm 包最小化设置
  • 解决iview多表头动态更改列元素发生的错误
  • 跨域
  • 力扣(LeetCode)56
  • 深入浅出webpack学习(1)--核心概念
  • 小程序button引导用户授权
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • #、%和$符号在OGNL表达式中经常出现
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • $$$$GB2312-80区位编码表$$$$
  • (30)数组元素和与数字和的绝对差
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (day 12)JavaScript学习笔记(数组3)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (八)Flask之app.route装饰器函数的参数
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (九)One-Wire总线-DS18B20
  • (七)c52学习之旅-中断
  • (三十五)大数据实战——Superset可视化平台搭建
  • (一)Neo4j下载安装以及初次使用
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • *上位机的定义
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET MAUI学习笔记——2.构建第一个程序_初级篇
  • .NET Remoting学习笔记(三)信道
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献