【Linux】详解线程控制之线程创建线程终止线程等待线程分离

news2024/9/20 16:51:36

一、线程创建

thread:这是一个指向pthread_t类型的指针,用于获取新创建线程的线程ID。在调用pthread_create后,这个指针会被设置为新线程的ID。

attr:这是一个指向pthread_attr_t类型的指针,用于设置线程的属性,如栈大小、优先级等。如果这个参数为NULL,那么线程将使用默认的属性。通常情况下,如果你不需要设置特殊的线程属性,可以传递NULL。

 

start_routine:这是一个函数指针,指向线程开始执行时要调用的函数。这个函数通常被称为线程的“入口点”或“启动例程”。

arg:用于向线程的启动例程传递参数。你可以通过这个参数向线程传递任何类型的数据。如果你的启动例程不需要任何参数,可以传递NULL。

二、线程终止

终止线程的三种方法:

  1. 在线程函数的内部使用return语句。
  2. 在线程函数的内部使用pthread_exit函数。
  3. 在主线程中使用pthread_cancel函数,可以回收指定的子线程。

2.1、pthread_exit函数

         pthread_exit函数中可以设置retval返回值,在主线程中可以调用pthread_join函数来获取子线程的返回值

2.2、pthread_cancel函数

        在主线程中使用pthread_cancel函数,在pthread_cancel函数中传入子进程的id可以直接终止子线程,不用等子线程跑完

2.3、注意点

不能用exit终止线程,因为exit是用来终止进程的,一旦exit执行了,那么整个进程也就退出了

三、线程等待回收

线程也要被等待回收,不然会出现类似于进程等待那里的僵尸问题,也就是出现内存泄漏。

        pthread_join函数可以用来回收子线程,第一个参数为子线程的id, 第二个参数可以得到子线程的退出信息。主线程退出整个进程就跟着退出了,也就意味着主线程退出所有线程都要跟着退出,所以我们一般需要主线程最后退出来等待回收子线程

四、线程创建、终止、回收的例子

        下面由主线程创建一批子线程,分配给子线程任务,子线程将结果封装起来并返回给主线程,主线程由此可以获取子线程的执行结果。

对任务进行封装,让子线程去执行加法任务:

class Task
{
private:
    int _x;
    int _y;
public:
    Task(int x, int y)
    :_x(x), _y(y)
    {}

    int Add()
    {
        return _x + _y;
    }
    ~Task()
    {}
};

分配给子线程任务,并回收结果:

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <vector>
using namespace std;

class ThreadData
{
private:
    Task _t;
    string _name;
public:
    ThreadData(Task t, string name)
    :_t(t), _name(name)
    {}

    Task getTask()
    {
        return _t;
    }

    string getName()
    {
        return _name;
    }
    ~ThreadData()
    {}
};
//结果封装
class Res
{
private:
    int _result;
    string _name;
public:
    Res(int result, string name)
    :_result(result)
    ,_name(name)
    {}

    int getResult()
    {
        return _result;
    }

    string getName()
    {
        return _name;
    }
    ~Res()
    {}
};
//子线程执行的函数
void* handler(void* args)
{
    ThreadData* th = (ThreadData*)args;
    Res* res = new Res(th->getTask().Add(), th->getName());
    delete th;
    return res;
}

vector<pthread_t> vect_tid;
vector<Res*> vect_res;
int main()
{
    for(int i = 0; i<5; i++)
    {
        pthread_t tid;
        Task task(10, 20);
        char buffer[1024];
        snprintf(buffer, sizeof(buffer), "thread-%d", i+1);
        ThreadData* th = new ThreadData(task, buffer);
        pthread_create(&tid, nullptr, handler, th);
        vect_tid.push_back(tid);
    }

    for(auto& e : vect_tid)
    {
        void* ret = nullptr;
        pthread_join(e, &ret);
        vect_res.push_back((Res*)(ret));
    }

    for(auto& e : vect_res)
    {
        cout << e->getName() << " " << "res=" << e->getResult() << endl;
        delete e;
    }
    return 0;
}

五、线程分离

        线程被创建出来的时候默认是joinable的,也就是说需要被等待的。如果我们的主线程并不关心新线程的执行结果,我们可以将新线程设置为分离状态。所谓的分离只是进程的一种工作状态,在底层依旧数据共享,依旧属于同一个进程

#include <iostream>
#include <pthread.h>
#include <unistd.h>

void* handler(void* args)
{
    const std::string str = static_cast<const char*> (args);
    int cnt = 5;
    while(cnt--)
    {
        std::cout << str << std::endl;
        sleep(1);
    }

    return nullptr;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, nullptr, handler, (void*)"new Thread");
    //detach可以放在main函数中也可以放在handler函数中
    pthread_detach(tid);
    while(true)
    {}
    return 0;
}

        分离之后再主线程中就不需要再对子线程进行等待回收了,即不需要在主线程中调用pthread_join函数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1693933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

零基础的粉丝有福了:逐键提示盲打更轻松

盲打就是不看键盘去打字&#xff0c;对于零基础的粉丝而言&#xff0c;盲打入门通常都是很难的&#xff0c;今天就给大家放个福利&#xff1a;从今天开始就能盲打&#xff0c;3天之后盲打就入门了。 真的有这么简单吗&#xff1f;是的&#xff0c;跟着我做就可以了。 首先&am…

Leetcode刷题笔记2:数组基础2

导语 leetcode刷题笔记记录&#xff0c;本篇博客记录数组基础1部分的题目&#xff0c;主要题目包括&#xff1a; 977.有序数组的平方 &#xff0c;209.长度最小的子数组 &#xff0c;59.螺旋矩阵II 知识点 滑动窗口 所谓滑动窗口&#xff0c;就是不断的调节子序列的起始位…

sysbench压测mysql性能测试命令和报告

sysbench压测mysql性能测试命令和报告 一、安装sysbench工具二、创建测试数据库三、基于sysbench构造测试表和测试数据四、数据库性能测试1、数据库读写性能测试2、数据库读性能测试3、数据库删除性能测试4、数据库更新索引字段性能测5、数据库更新非索引字段性能测试6、数据库…

[激光原理与应用-93]:激光焊接检测传感器中常用的聚焦镜、分色镜、分光镜、滤波镜

目录 一、聚焦镜 1.1 原理及作用 1.2 性能指标 1.3 应用 1.4 类型 二、分色镜 2.1 原理及应用 2.2 种类 2.3 特点 2.4 注意事项 2.5 性能指标 三、分光镜 ​编辑 3.1 分光镜的类型 3.2 分光镜的工作原理 3.3 分光镜的应用 3.4 分光镜的参数 3.5 分光镜的优点…

LabVIEW控制Trio控制器

将LabVIEW与Trio控制器结合&#xff0c;可以实现对复杂运动系统的控制和监测。以下是详细的方法和注意事项&#xff1a; 一、准备工作 软件安装&#xff1a; 安装LabVIEW开发环境&#xff0c;确保版本兼容性。 安装Trio控制器的相关驱动程序和软件&#xff0c;如Trio Motion …

Springboot集成GRPC

Springboot集成GRPC 一、springboot版本二、GRPC的pom依赖2.1 服务端2.2 客户端3.构建依赖 三、配置文件服务端客户端 四、 demo4.1 编写proto文件4.2 生成文件4.3 服务端重写方法4.4 客户端调用该方法 五、测试 一、springboot版本 <groupId>org.springframework.boot&l…

数理逻辑:1、预备知识

17.1 命题和联结词 ​ 命题&#xff1a;可以判定真假的陈述句。&#xff08;则悖论&#xff0c;祈使句&#xff0c;疑问句都不是命题&#xff09; ​ 原子命题&#xff1a;不能被分割为更小的命题的命题 例如&#xff1a; 2既是素数又是偶数 可以由$p: 2 是素数&#xff0c;…

AI模型抉择:开源VS闭源,谁主沉浮?

AI模型抉择&#xff1a;开源VS闭源&#xff0c;谁主沉浮&#xff1f; &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &am…

C++字符编码 cppp-reiconv库使用详解

经常写一些控制台小程序&#xff0c;常常会遇到输出中文乱码的问题&#xff0c;在windwos下可以使用MultiByteToWideChar转换字符编码&#xff0c;但跨平台就需要cppp-reiconv这样的第三方字符编码处理库&#xff0c;且开源。 一、下载cppp-reiconv库的源码和静/动态库 GitHu…

Windows11搭建Flutter3开发环境

下载&#xff1a;https://docs.flutter.cn/get-started/install/windows/desktop?tabdownload 下载以后解压到C盘&#xff1a; 将bin目录添加到环境变量PATH&#xff1a; 打开终端&#xff0c;输入&#xff1a; flutter doctor执行下面的命令&#xff0c;同意安卓协议&am…

【linux】docker下nextcloud安装人脸识别插件

一、插件源码地址&#xff1a; GitCode - 开发者的代码家园 二、插件官网地址&#xff1a; Releases - Face Recognition - Apps - App Store - Nextcloud 三、插件安装教程&#xff1a; 1、查看本地nextcloud版本号 http://ipAddress:8080/settings/admin/overview 2、找…

GpuMall智算云:meta-llama/llama3/Llama3-8B-Instruct-WebUI

LLaMA 模型的第三代&#xff0c;是 LLaMA 2 的一个更大和更强的版本。LLaMA 3 拥有 35 亿个参数&#xff0c;训练在更大的文本数据集上GpuMall智算云 | 省钱、好用、弹性。租GPU就上GpuMall,面向AI开发者的GPU云平台 Llama 3 的推出标志着 Meta 基于 Llama 2 架构推出了四个新…

DNS的服务与部署(2)

1、dns的安装及开启 dnf install bind.x86_64 -y #安装 #Berkeley Internet Name Domain (BIND) systemctl enable --now named #启用dns服务&#xff0c;服务名称叫named firewall-cmd --permanent --add-servicedns #火墙设置 firewall-cmd --reload …

C# 拓展方法(涉及Linq)

拓展方法 定义一个扩展方法使用扩展方法例如再举个例子终极例子 注意事项与Linq 在C#中&#xff0c;扩展方法是一种特殊的静态方法&#xff0c;允许开发者向现有类型“添加”新的方法&#xff0c;而无需修改该类型的源代码或创建新的派生类型。这种机制提供了一种更为灵活的方式…

解禁谷歌等浏览器禁止网站使用麦克等媒体设备

1、浏览器地址栏输入chrome://flags/ 微软的chromium内核的edge浏览器&#xff0c;既可以输入&#xff1a;chrome://flags/ &#xff0c;也可以输入edge://flags/ 2、打开后&#xff0c;界面如下 3、输入搜索&#xff0c;unsafe&#xff0c;并启用、输入需要启用的网址

【算法】前缀和——寻找数组的中心下标

本节博客是用前缀和算法图解“寻找数组的中心下标”&#xff0c;有需要借鉴即可。 目录 1.题目2.题意3.前缀和求解4.示例代码5.细节6.总结 1.题目 题目链接&#xff1a;LINK 2.题意 我们以示例1为例来图解一下题意&#xff1a; 3.前缀和求解 根据已有经验&#xff0c;我…

低功耗蓝牙模块轻松实现智能防丢器

低功耗蓝牙模块&#xff0c;作为集成蓝牙无线技术功能的PCBA板&#xff0c;主要用于短距离无线通讯&#xff0c;已经成为物联网无线传输发展的中坚力量。随着蓝牙技术不断更新换代&#xff0c;越来越多的智能可穿戴设备出现在我们的生活中&#xff0c;智能手环&#xff0c;智能…

634 · 单词矩阵

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; . - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; class Solution { public: struct Trie {Trie() {next.resize(26, nullptr);end false;} std::vector<Trie*> next; b…

2024最新php项目加密源码

压缩包里有多少个php就会被加密多少个PHP、php无需安装任何插件。源码全开源 如果上传的压缩包里有子文件夹&#xff08;子文件夹里的php文件也会被加密&#xff09;&#xff0c;加密后的压缩包需要先修复一下&#xff0c;步骤&#xff1a;打开压缩包 》 工具 》 修复压缩文件…

2024-05学习笔记

最近的学习大多都是和mysql的索引相关的 1.mvcc mvcc是不需要手动配置&#xff0c;是mysql的一个机制 在事务开启时&#xff0c;对涉及到的数据加一个隐藏列&#xff0c;隐藏列对应的值&#xff0c;就是事务id 如果当前是修改操作&#xff0c;就copy一份原来的数据到新的一行…