linux下线程分离属性

linux下线程分离属性

一、线程的属性---分离属性

什么是分离属性?

首先分离属性是线程的一个属性,有了分离属性的线程,不需要别的线程去接合自己的(回收自己的资源)。

a.线程的分离属性有两种:分离态 (detached)和非分离态(joinable)。

b.非分离态的线程只有在调用pthread_join之后才会完全释放自己所占用的资源,可以用pthread_detach函数将线程修改为分离态,分离态的线程在线程结束后由系统自动释放其所占用的所有资源;

c.线程创建后默认属性是非分离态,需要调用pthread_join释放线程所占用的资源;

但是虽然说是分离的,但是进程退出了,该线程还是会退出的。
总结:

设置了分离属性的线程 -> 不需要pthread_join()

设置了非分离属性的线程 -> 需要pthread_join() -> 默认创建的普通属性线程就是非分离线程。

退出进程,所有子线程都会消亡,系统会回收他们资源。

如果设置为非分离属性的线程,且不去回收子线程资源,那么一个进程创建的子线程数据是有限,请下面程序(环境ubuntu20.04 64位)

c 复制代码
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

//定义退出的值为全局变量
int retval = 10;

//子线程
void *start_pthread(void *arg)
{
    int cnt = 0;

    printf("arg:%ld\n", *((unsigned long *)arg));

}


int main(void)
{
    int cnt = 0;

    unsigned long val = 0;

    pthread_t  thread_id;


    //主线程 运行时间比子线程时间长,主线程运行退出后,回收子线程资源
     while (1)
     {
        //线程创建 非分离
        int ret = pthread_create(&thread_id, NULL, start_pthread, &val);

        if(ret != 0)
        {
            printf("pthread_create fail\n");
            return -1;
        }    
        val++;

     }



    printf("接合子线程成功\n");
     
    return 0;

}

运行效果

如果不设置为分离属性(主不回收子线程资源),创建到32749条时,创建线程失败

二、线程属性设置

线程属性设置通常有两个种,一种是在创建前设置好分离属性,别一个种是线程运行后,再设置线程属性接下来先看第一种情况。

2.1 线程创建前设置分离属性

线程创建前设置分离属性就是添加一个分离属性到一个属性变量中,然后使用属性变量去创建一个线程,那么创建出来的线程就是具有分离属性的线程。

接下来看函数

1)定义一个属性变量 -> 数据类型:pthread_attr_t

c 复制代码
pthread_attr_t attr;

2)初始化属性变量。 -> pthread_attr_init() -> man 3 pthread_attr_init

c 复制代码
#include <pthread.h>
int pthread_attr_init(pthread_attr_t *attr);

参数:

attr:未初始化的属性变量

返回值:

成功:0

失败:非0错误码

3)设置分离属性到属性变量中。

c 复制代码
#include <pthread.h>
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

参数:

attr:已经初始化过的属性变量

detachstate:

PTHREAD_CREATE_DETACHED -> 分离属性

PTHREAD_CREATE_JOINABLE -> 非分离属性 等同于 pthread_create(&thread_id, NULL, start_pthread, &val);

返回值:

成功:0

失败:非0错误码

4)使用属性变量去创建一个新的线程。

c 复制代码
pthread_create(&tid,&attr,.....);   -> 创建出来的线程就是分离属性的线程,不需要pthread_join()

5)销毁属性变量。 -> pthread_attr_destroy() -> man 3 pthread_attr_destroy

c 复制代码
int pthread_attr_destroy(pthread_attr_t *attr);

参数:

attr:已经初始化过的属性变量

返回值:

成功:0

失败:非0错误码

案例代码

c 复制代码
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

//定义退出的值为全局变量
int retval = 10;

//子线程有分离--不需要接合
void *start_pthread(void *arg)
{
    int cnt = 0;

    printf("arg:%ld\n", *((unsigned long *)arg));

}


int main(void)
{
    int cnt = 0;

    unsigned long val = 0;

    pthread_t  thread_id;
    //定义分享属性变量 
    pthread_attr_t attr;

    //初始化属性变量
    pthread_attr_init(&attr);

    //设置线程属性--分离属性
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    //主线程 运行时间比子线程时间长,主线程运行退出后,回收子线程资源
     while (1)
     {
        //线程创建 分离属性
        int ret = pthread_create(&thread_id, &attr, start_pthread, &val);

        if(ret != 0)
        {
            printf("pthread_create fail\n");
            return -1;
        }    
        val++;

     }



    printf("接合子线程成功\n");
     
    return 0;

}

分离属性后的线程,可以自动消亡,主线程可以无限创建子线程。

2.2 线程创建后设置分离属性

先创建一个普通线程(分享属性设置为NULL, 默认的分享属性为不分离),然后在线程中调用一个设置分离属性的函数,那么这个线程就变成分离的属性。

1)设置线程本身的属性为分离属性。 -> pthread_detach() -> man 3 pthread_detach

c 复制代码
#include <pthread.h>
int pthread_detach(pthread_t thread);

函数作用:

设置分离属性给线程

参数:

thread:需要设置分离属性的线程的ID号

返回值:

成功:0

失败:非0错误码

2)获取线程的ID号。 -> pthread_self() -> man 3 pthread_self

c 复制代码
#include <pthread.h>
pthread_t pthread_self(void);

参数:

无

返回值:线程的ID号。

案例

c 复制代码
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>



//子线程
void *start_pthread(void *arg)
{
    int cnt = 0;

    //获取线程ID
    pthread_t thread_id = pthread_self();

    //分离线程
    int ret = pthread_detach(thread_id);
    if(ret != 0)
    {
        printf(" pthread_detach fail\n");
        exit(0);
    }

     printf("arg:%ld\n", *((unsigned long *)arg));

}


int main(void)
{
    unsigned long val = 0;

    pthread_t  thread_id;


    //主线程 运行时间比子线程时间长,主线程运行退出后,回收子线程资源
     while (1)
     {
        //线程创建 默认为非分离
        int ret = pthread_create(&thread_id, NULL, start_pthread, &val);

        if(ret != 0)
        {
            printf("pthread_create fail\n");
            return -1;
        }    
        val++;
     }
     


    return 0;

}

设置了分离属性之后,子线程可以无限被创建。

相关推荐
迷途之人不知返7 小时前
【文件系统】-4-软硬连接
linux
1234567890@world9 小时前
正点原子 ATK-DLRK3568 嵌入式Linux系统开发手册V1.3 详细总结
linux·stm32·单片机
sun_weitao9 小时前
极简版 MCP 工具实现方案
java·linux·服务器
爱和冰阔落11 小时前
【Linux】线程安全进阶:单例模式、可重入函数与死锁排查
linux·运维·安全·单例模式
先知后行。11 小时前
pimpl
linux
q275513004212 小时前
AS8132 DP转HDMI 4K60(420)被动式 国产性价比AS方案
linux·算法·硬件架构·dash
刚入门的大一新生13 小时前
Linux-进程间通信2
linux·运维·服务器
电科_银尘13 小时前
【深度学习项目实战·02】Linux服务器环境搭建:从SSH登录到稳定运行项目
linux·服务器·深度学习
运维小斌14 小时前
麒麟 V10 部署 OceanBase:故障速查与验收清单
linux·数据库·oceanbase·麒麟
水饺编程14 小时前
第2章:Linux 基础,在 root 中创建用户账号
linux·c语言·汇编·1024程序员节