【Linux】C语言中多线程的创建、退出、回收、分离

这篇具有很好参考价值的文章主要介绍了【Linux】C语言中多线程的创建、退出、回收、分离。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

线程是轻量级的进程(LWP:light weight process),在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合,指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位,分配系统资源,可以这样理解,进程是资源分配的最小单位,线程是操作系统调度执行的最小单位

在Linux系统下,线程的创建和管理是通过pthread库实现的。pthread是POSIX线程库,提供了创建、终止、同步和通信线程的函数和数据结构。

创建线程

线程函数

每一个线程都有一个唯一的线程 ID,ID 类型为 pthread_t,这个 ID 是一个无符号长整形数,如果想要得到当前线程的线程 ID,可以调用如下函数:

pthread_t pthread_self(void);	// 返回当前线程的线程ID

在Linux系统下,可以使用pthread_create函数来创建线程。pthread_create函数的原型如下:

#include <pthread.h>

int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine)(void*), void* arg);

  • thread:指向pthread_t类型的指针,用于存储新创建线程的标识符。在成功创建线程后,该指针将被填充为一个唯一的标识符,用于后续对线程的引用。
  • attr:指向pthread_attr_t类型的指针,用于指定线程的属性。线程属性对象可以控制线程的各种行为,例如线程的调度策略、栈大小、分离状态等。如果不需要对线程属性进行特殊设置,可以传入NULL,使用默认属性。
  • start_routine:指向线程函数的指针,该函数是线程的入口点。线程函数是线程的实际执行体,当线程被创建时,将从该函数开始执行。函数的返回类型必须为void*,并接受一个void*类型的参数。线程函数可以执行任意操作,包括计算、访问共享资源等。
  • arg:传递给线程函数的参数,类型为void*。可以将任意类型的数据传递给线程函数,只需将其转换为void*类型。在线程函数内部,可以使用适当的类型转换将参数恢复为原始类型。

返回值:线程创建成功返回 0,创建失败返回对应的错误号

在编写多线程程序的时候,如果想要让线程退出,但是不会导致虚拟地址空间的释放(针对于主线程),我们就可以调用线程库中的线程退出函数,只要调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行,不管是在子线程或者主线程中都可以使用。

void pthread_exit(void *retval);

参数 retval 是一个指向任意类型的指针,表示线程的退出状态。线程的退出状态可以用于与其他线程进行通信或传递结果。

pthread_self() 是一个 POSIX 线程库函数,用于获取当前线程的线程 ID。

pthread_t pthread_self(void);

线程创建

注意:线程函数可以接受一个指向任意类型的参数,并且返回一个指向任意类型的指针。
首先使用vim pthread_create.c创建c语言文件。
键入代码:

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

void *callback(void* arg)
{
        for(int i=0;i<5;++i)
                {
                        printf("子线程:i=%d\n",i);

                }
        printf("子线程:%ld\n",pthread_self());
        return NULL;
}

int main()
{
        pthread_t tid;
        pthread_create(&tid,NULL,callback,NULL);
        for(int i=0;i<5;++i)
        {
                printf("主线程:i=%d\n",i);
        }
        printf("主线程:%ld\n",pthread_self());
        pthread_exit(NULL);
        return 0;
}

保存文件后使用g++ pthread_create.c -lpthread -o app命令进行编译。
该命令用于编译名为 pthread_create.c 的源代码文件,并链接 pthread 库生成可执行文件 app。

g++:是 GNU 编译器集合中的 C++ 编译器。
pthread_create.c:是要编译的源代码文件的名称。
-lpthread:表示链接 pthread 库,这是 POSIX 线程库。
-o app2:指定生成的可执行文件的名称为 app2

【Linux】C语言中多线程的创建、退出、回收、分离
执行./app,结果如下所示
【Linux】C语言中多线程的创建、退出、回收、分离

线程回收

在线程编程中,线程回收是指等待线程执行结束并收回相关资源。在 POSIX 线程库中,可以使用 pthread_join 函数来实现线程的回收。pthread_join 函数的原型如下:

int pthread_join(pthread_t thread, void **retval);

其中,thread 参数是要回收的线程标识符,retval参数用于接收线程的返回值。函数的返回值表示回收线程的执行状态,如果成功回收线程,则返回 0,否则返回一个非零值,表示出现了错误。

当调用 pthread_join 函数时,当前线程会被阻塞,直到指定的线程执行结束。一旦线程执行结束,它的资源将被回收,并可以通过 retval 参数获取线程的返回值。

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<pthread.h>
struct persion
{
int num;
int age;
};
void *callback(void* arg)
{
        for(int i=0;i<5;++i)
                {
                        printf("子线程:i=%d\n",i);

                }
        printf("子线程:%ld\n",pthread_self());
        struct persion* t = (struct persion*)arg;
        t->num=100;
        t->age=5;
        pthread_exit(&t);
        return NULL;
}

int main()
{
        pthread_t tid;
        struct persion t;
        pthread_create(&tid,NULL,callback,&t);
        for(int i=0;i<5;++i)
        {
                printf("主线程:i=%d\n",i);
        }
        printf("主线程:%ld\n",pthread_self());
        void *ptr;
        pthread_join(tid,&ptr);
        struct persion *pt=(struct persion*)ptr;
        printf("num:%d,age:%d\n",t.num,t.age);
        pthread_exit(NULL);
        return 0;
}

pthread_join其实是个阻塞函数,如果还有子线程在运行,调用该函数就会阻塞,子线程退出函数解除阻塞进行资源的回收,函数被调用一次,只能回收一个子线程,如果有多个子线程则需要循环进行回收。

ptr 用于接收子线程的返回值,pt 通过强制类型转换指向子线程的返回值,而 t 是主线程中的一个独立对象

结果如下所示:
【Linux】C语言中多线程的创建、退出、回收、分离

线程分离

线程的分离是指将线程设置为分离状态,使其在退出时自动释放资源,不需要显式地调用 pthread_join 函数来等待线程的结束。

在某些情况下,程序中的主线程有属于自己的业务处理流程,如果让主线程负责子线程的资源回收,调用 pthread_join() 只要子线程不退出主线程就会一直被阻塞,主要线程的任务也就不能被执行了。

线程分离之后在主线程中使用 pthread_join() 就回收不到子线程资源了。

        for(int i=0;i<5;++i)
                {
                        printf("子线程:i=%d\n",i);

                }
        printf("子线程:%ld\n",pthread_self());
        struct persion* t = (struct persion*)arg;
        t->num=100;
        t->age=5;
        pthread_exit(&t);
        return NULL;
}

int main()
{
        pthread_t tid;
        struct persion t;
        pthread_create(&tid,NULL,callback,&t);
        for(int i=0;i<5;++i)
        {
                printf("主线程:i=%d\n",i);
        }
        printf("主线程:%ld\n",pthread_self());
        pthread_detach(tid);
        pthread_exit(NULL);

        return 0;
}

线程分离后,子线程执行完毕后被系统内核回收了,且主线程退出后不会影响子线程的执行。文章来源地址https://www.toymoban.com/news/detail-494379.html

到了这里,关于【Linux】C语言中多线程的创建、退出、回收、分离的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux系统编程:线程】 线程控制 -- 创建、终止、等待、分离 | 线程互斥与同步 | 互斥量与条件变量 | 生产者消费者模型 | 线程池 | STL/智能指针与线程安全 | 读者写者模型

    写在前面 本文重点: 了解线程概念,理解线程与进程区别与联系。 学会线程控制,线程创建,线程终止,线程等待。 了解线程分离与线程安全。 学会线程同步。 学会使用互斥量,条件变量,posix 信号量,以及读写锁。 理解基于读写锁的读者写者问题。 一、线程概念 💦

    2024年02月04日
    浏览(70)
  • Linux中 socket编程中多进程/多线程TCP并发服务器模型

    一次只能处理一个客户端的请求,等这个客户端退出后,才能处理下一个客户端。 缺点:循环服务器所处理的客户端不能有耗时操作。 模型 源码 可以同时处理多个客户端请求 父进程 / 主线程专门用于负责连接,创建子进程 / 分支线程用来与客户端交互。 模型 源码 模型 源

    2024年02月12日
    浏览(42)
  • 【linux 多线程并发】线程退出自动清理函数的使用,释放线程申请的资源,异常退出自动调用

    ​ 专栏内容 : 参天引擎内核架构 本专栏一起来聊聊参天引擎内核架构,以及如何实现多机的数据库节点的多读多写,与传统主备,MPP的区别,技术难点的分析,数据元数据同步,多主节点的情况下对故障容灾的支持。 手写数据库toadb 本专栏主要介绍如何从零开发,开发的

    2024年02月02日
    浏览(47)
  • Linux线程(4)——pthread_detach()自动回收线程资源

    分离线程                 默认情况下,当线程终止时,其它线程可以通过调用 pthread_join()获取其返回状态、回收线程资源,有时,程序员并不关心线程的返回状态,只是希望系统在线程终止时能够自动回收线程资源并将其移除。在这种情况下,可以调用 pthread_detach

    2024年02月03日
    浏览(41)
  • java中多线程

    进程 进程:是正在运行的程序 是系统进行资源分配和调用的独立单位 每个进程都具有它自己的存储空间和系统资源 线程 线程:是进程中的单个顺序控制流,是一条执行路径 单线程:一个进程如果只有一条执行路径,则称之为单线程程序 多线程:一个进程如果有多条执行路

    2024年01月17日
    浏览(46)
  • 【Linux】线程分离 | 线程库 | C++调用线程 | 线程局部存储

    1. 为什么要线程分离? 使用 pthread_join 默认是阻塞的 ,即主线程等待 新线程退出 在这个过程中,主线程会直接卡住,就没办法继续向后运行,也就什么都干不了 若主线程 想做其他事情 ,所以就提出了 线程分离的概念 默认情况下,新创建的线程是joinable的 即 线程默认被创

    2024年02月06日
    浏览(37)
  • Qt中多线程的使用

    在进行桌面应用程序开发的时候, 假设应用程序在某些情况下需要处理比较复杂的逻辑, 如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使用多线程,其中一个线程处理窗口事件,其他线程进行逻辑运算,多个线程各司其职,不

    2024年02月11日
    浏览(44)
  • Qt 中多线程的使用

    在进行桌面应用程序开发的时候, 假设应用程序在某些情况下需要处理比较复杂的逻辑, 如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。这种情况下就需要使用多线程,其中一个线程处理窗口事件,其他线程进行逻辑运算,多个线程各司其职,不

    2024年02月03日
    浏览(47)
  • C#中多线程Task详解

    参考文章: 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 添加链接描述 1.1Thread方式 缺点:频繁的创建和消耗比较好资源;提供操作线程的API不是马上响应(线程是

    2024年02月04日
    浏览(47)
  • 【Linux C | 多线程编程】线程的连接、分离,资源销毁情况

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 ⏰发布时间⏰:2024-04-01 14:52:46 本文未经允许,不得转发!!! 记住一句话,“创建线程后,要么连接该线程,要么使该线程分离,否则可能导致资源无法

    2024年04月13日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包