【Linux系统编程】第四十三弹---多线程编程指南:线程终止方式与C++11中的thread

news2024/11/8 11:42:03

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、线程终止

1.1、pthread_exit() 

1.2、pthread_cancel() 

1.3、pthread_detach() 

2、C++11中thread 


1、线程终止

问题7 : 新线程如何终止?

1、线程函数 return 

2、pthread_exit 

3、main thread call pthread_cancel ,新线程退出结果是-1 

上一弹已经演示了使用函数return终止进程的方式,此处就只介绍后两种方式了!

可不可以使用我们前面学习过的exit函数终止线程呢?

答案是不能,exit是专门用来终止进程的!

const int num = 10;

void *threadrun(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(1);
        break; // 1秒后退出循环
    }
    exit(1); // 进程: 专门用来终止进程的,不能终止线程
}

// main函数结束: main thread 结束,表示进程结束!
int main()
{
    std::vector<pthread_t> tids;
    for (int i = 0; i < num; i++)
    {
        // 1.有线程的id
        pthread_t tid;
        // 2.有线程的名字(正确示范)
        char* name  = new char[128];
        snprintf(name, 128, "thread-%d", i + 1);
        pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
        // 3.保存所有线程的id信息
        tids.emplace_back(tid);
    }
    for(auto tid : tids)
    {
        void* name = nullptr;
        pthread_join(tid,&name);
        std::cout << (const char*)name << " quit" << std::endl;
        delete (const char*)name;
    }
    // 主线程不退
    sleep(100);
    return 0;
}

1.1、pthread_exit() 

pthread_exit()

pthread_exit - 退出一个线程

#include <pthread.h>

void pthread_exit(void *retval);

参数:

  • retval:这是一个指向返回值的指针,该返回值可以被其他线程通过 pthread_join 函数获取。如果线程不需要返回任何值,可以将此参数设置为 nullptr。

代码演示

修改上面新线程函数代码即可!

void *threadrun(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(1);
        break; // 1秒后退出循环
    }
    pthread_exit(args); // 专门终止一个线程的!
}

运行结果 

1.2、pthread_cancel() 

 方式三:pthread_cancel

pthread_cancel()

pthread_cancel - 向指定的线程发送取消请求

#include <pthread.h>

int pthread_cancel(pthread_t thread);

参数

  • thread:指定需要取消的目标线程的标识符。

返回值

  • 成功时返回 0
  • 失败时返回非零值,并设置相应的错误码。

代码演示

const int num = 10;

void *threadrun(void *args)
{
    std::string name = static_cast<const char *>(args);
    // 死循环
    while (true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(1);
    }
    pthread_exit(args); // 专门终止一个线程的!
}

// main函数结束: main thread 结束,表示进程结束!
int main()
{
    std::vector<pthread_t> tids;
    for (int i = 0; i < num; i++)
    {
        // 1.有线程的id
        pthread_t tid;
        // 2.有线程的名字(正确示范)
        char* name  = new char[128];
        snprintf(name, 128, "thread-%d", i + 1);
        pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
        // 3.保存所有线程的id信息
        tids.emplace_back(tid);
    }
    sleep(3);
    // join todo
    for(auto tid : tids)
    {
        pthread_cancel(tid); // 取消新线程
        std::cout << "cancel: " << PrintToHex(tid) << std::endl;
        void* result = nullptr; // 线程被取消线程的退出结果是:-1 #define PTHREAD_CANCELED ((void *) -1)
        pthread_join(tid,&result);
        std::cout << (long long int)result << " quit" << std::endl;
    }
    // 主线程不退
    sleep(100);
    return 0;
}

 运行结果 

问题8: 可不可以不join线程,让它执行完就退出呢?

可以!detach分离

a. 一个线程被创建,默认是joinable的,必须要被join的.

b. 如果一个线程被分离,线程的工作状态分离状态,不需要/不能被join的. 依旧属于进程内部,但是不需要被等待了

1.3、pthread_detach() 

pthread_detach - 将指定的线程设置为分离状态

#include <pthread.h>

int pthread_detach(pthread_t thread);

参数

  • thread:指定要设置为分离状态的线程的标识符。

返回值

  • 成功时返回 0
  • 失败时返回非零值,并设置相应的错误码。
pthread_self - 获取当前线程的线程标识符

#include <pthread.h>

pthread_t pthread_self(void);

返回值

pthread_self 函数返回一个 pthread_t 类型的值,该值表示调用线程的线程标识符。这个标识符是一个不透明的数据类型,通常用于在线程管理、线程间通信和同步等操作中标识当前线程。

不分离线程且终止线程

代码演示

const int num = 10;

void *threadrun(void *args)
{
    // pthread_detach(pthread_self());
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(1);
        break; // 1秒后退出循环
    }
    pthread_exit(args); 
}

int main()
{
    std::vector<pthread_t> tids;
    for (int i = 0; i < num; i++)
    {
        pthread_t tid;
        char* name  = new char[128];
        snprintf(name, 128, "thread-%d", i + 1);
        pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
        tids.emplace_back(tid);
    }
    // join todo
    for(auto tid : tids)
    {
        void* name = nullptr;
        int n = pthread_join(tid,&name);
        std::cout << (const char*)name << " quit...,n: " << n << std::endl;
        delete (const char*)name;
    }
    // 主线程不退
    sleep(100);
    return 0;
}

运行结果  

新线程分离自己

代码演示

const int num = 10;

void *threadrun(void *args)
{
    pthread_detach(pthread_self());
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(1);
        break; 
    }
    pthread_exit(args); 
}

int main()
{
    std::vector<pthread_t> tids;
    for (int i = 0; i < num; i++)
    {
        pthread_t tid;
        char* name  = new char[128];
        snprintf(name, 128, "thread-%d", i + 1);
        pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
        tids.emplace_back(tid);
    }
    // sleep(1);
    // join todo
    for(auto tid : tids)
    {
        void* result = nullptr;
        int n = pthread_join(tid,&result);
        std::cout << (long long int)result << " quit...,n: " << n << std::endl;
    }
    // 主线程不退
    //sleep(100);
    return 0;
}

运行结果  

主线程分离新线程

代码演示

void *threadrun(void *args)
{
    std::string name = static_cast<const char *>(args);
    while (true)
    {
        std::cout << name << " is running" << std::endl;
        sleep(1);
        break; 
    }
    pthread_exit(args); 
}

int main()
{
    std::vector<pthread_t> tids;
    for (int i = 0; i < num; i++)
    {
        pthread_t tid;
        char* name  = new char[128];
        snprintf(name, 128, "thread-%d", i + 1);
        pthread_create(&tid, nullptr, threadrun, /*线程的名字*/ name);
        tids.emplace_back(tid);
    }

    for(auto tid : tids)
    {
        pthread_detach(tid);// 主线程分离新线程,前提新线程需要存在
    }

    // 分离后无需join
    for(auto tid : tids)
    {
        void* result = nullptr;
        int n = pthread_join(tid,&result);
        std::cout << (long long int)result << " quit...,n: " << n << std::endl;
    }
    return 0;
}

 运行结果 

2、C++11中thread 

C++11多线程的本质就是对原生线程库接口的封装。

代码演示 

void threadrun(std::string name,int num)
{
    while(num)
    {
        std::cout << name << " num : " << num<< std::endl;
        num--;
        sleep(1);
    }
}

int main()
{
    std::string name = "thread-1";
    std::thread mythread(threadrun,name,10); // 创建线程
    while(true)
    {
        std::cout << "main thhread..." << std::endl;
        sleep(1);
    }
    mythread.join(); // 终止线程
    return 0;
}

运行结果  

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

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

相关文章

【Mac】PD报错:无法为“Windows” 完成操作,虚拟机ID无效的解决办法

Parallels Desktop是Mac上一款非常常用的虚拟机软件&#xff0c;但是在使用过程中&#xff0c;可能会遇到一些问题不知道如何处理。比如有时会遇到PD报错&#xff1a;无法为“Windows 11”完成操作&#xff0c;虚拟机ID无效。 错误原因 电脑上安装过虚拟机&#xff0c;虚拟机被…

25-RVIZ CARLA插件

RVIZ插件(RVIZ plugin)提供了一个基于RVIZ(RVIZ) ROS包的可视化工具。 用RVIZ运行ROS桥接 RVIZ插件需要一个名为ego_vehicle的自车。要查看ROS-bridge使用RVIZ的示例&#xff0c;请在运行CARLA服务器的情况下执行以下命令&#xff1a; 1. 启用RVIZ启动ROS桥接&#xff1a; # …

spark-本地模式的配置和简单使用

python环境的安装 在虚拟机中&#xff0c;只能安装一个python的版本&#xff0c;若想要安装别的版本&#xff0c;则需要卸载之前的版本——解决方式&#xff0c;安装Anaconda 通过百度网盘分享的文件&#xff1a;Anaconda3-2021.05-Linux-x86_64.sh 链接&#xff1a;https://…

【算法】递归+回溯+剪枝:78.子集

目录 1、题目链接 2、题目 3、解法(回溯剪枝) 4、代码 1、题目链接 78.子集&#xff08;LeetCode&#xff09; 2、题目 3、解法(回溯剪枝) 思路&#xff1a; 枚举子集&#xff08;答案&#xff09;的第一个数选谁&#xff0c;第二个数选谁&#xff0c;第三个数选谁&#x…

Aop+自定义注解实现数据字典映射

数据字典 Web项目开发中&#xff0c;字典表的一般都会存在&#xff0c;主要用来给整个系统提供基础服务。 比如男女性别的类型可以使用0和1来进行表示&#xff0c;在存储数据和查询数据的时候&#xff0c;就可以使用字典表中的数据进行翻译处理。 再比如之前做的一个项目中宠物…

【NLP自然语言处理】深入探索Self-Attention:自注意力机制详解

目录 &#x1f354; Self-attention的特点 &#x1f354; Self-attention中的归一化概述 &#x1f354; softmax的梯度变化 3.1 softmax函数的输入分布是如何影响输出的 3.2 softmax函数在反向传播的过程中是如何梯度求导的 3.3 softmax函数出现梯度消失现象的原因 &…

华为eNSP:QinQ

一、什么是QinQ&#xff1f; QinQ是一种网络技术&#xff0c;全称为"Quantum Insertion"&#xff0c;也被称为"Q-in-Q"、"Double Tagging"或"VLAN stacking"。它是一种在现有的VLAN&#xff08;Virtual Local Area Network&#xff0…

细说STM32单片机USART中断收发RTC实时时间并改善其鲁棒性的另一种方法

目录 一、工程目的 1、目标 2、通讯协议及应对错误指令的处理目标 二、工程设置 三、程序改进 四、下载与调试 1、合规的指令 2、不以#开头&#xff0c;但以&#xff1b;结束&#xff0c;长度不限 3、以#开头&#xff0c;不以;结束&#xff0c;也不包含;&#xff0c;长…

Redis设计与实现 学习笔记 第十六章 Sentinel

Sentinel&#xff08;哨岗、哨兵&#xff09;是Redis的高可用性&#xff08;high availability&#xff09;解决方案&#xff1a;由一个或多个Sentinel实例&#xff08;instance&#xff09;组成的Sentinel系统可以监视任意多个主服务器&#xff0c;以及这些主服务器属下的从服…

前端三件套-css

一、元素选择器 元素选择器&#xff1a;利用标签名称。p,h1-h6...... 行内样式&#xff08;内联样式&#xff09;&#xff1a;例如<p style"color:red;font-size:50px"> id选择器&#xff1a;针对某一个特定的标签来使用。以#定义。 class&#xff08;类&a…

MoonBit 双周报 Vol.59:新增编译器常量支持,改进未使用警告,支持跨包函数导入...多个关键技术持续优化中!

2024-11-04 MoonBit更新 增加了编译期常量的支持。常量的名字以大写字母开头&#xff0c;用语法 const C ... 声明。常量的类型必须是内建的数字类型或 String。常量可以当作普通的值使用&#xff0c;也可以用于模式匹配。常量的值目前只能是字面量&#xff1a; const MIN_…

新疆高校大数据实验室案例分享

高校大数据实验室建设&#xff0c;企业可以提供技术支持、实训平台和项目案例&#xff0c;高校则提供科研和教学资源&#xff0c;实现产学研一体化。不仅有利于大数据技术的应用和人才培养也有利于区域发展。 泰迪与新疆合作的院校包括新疆大学、昌吉学院等 新疆大…

Capcut,更适合做TikTok运营的“剪映”

剪映这一次的更新&#xff0c;可谓是引来许多视频创作者的怒火。原本免费的功能&#xff0c;更新之后需要vip才能使用了&#xff1b;原本的vip功能&#xff0c;则需要升级至svip&#xff0c;甚至一些功能&#xff0c;需要会员积分才能使用。 许多运营TikTok的小伙伴一直在用剪映…

linux centos 安装redis

安装 wget https://download.redis.io/releases/redis-7.4.0.tar.gz解压redis-7.4.0.tar.gz文件 tar -zxvf redis-7.4.0.tar.gz进入redis安装目录 cd redis-7.4.0make时报错&#xff0c;因为需要安装gcc&#xff0c;gcc安装需要联网安装 修改端口 编辑文件用vi。nano命令cen…

第一个纯血鸿蒙应用(Napi开发-ArtTS调用C/C++)

1.行业背景 纯血鸿蒙&#xff0c;即鸿蒙Next版已于2014年1月正式发版&#xff0c;鸿蒙生态设备数量已经突破10亿台&#xff0c;已经有超过15000个应用和元服务上架。鸿蒙生态不只是移动设备这么简单&#xff0c;他打造的是一个18n的全场景战略&#xff0c;真正做到了“万物互联…

2.ARM_ARM是什么

CPU工作原理 CPU与内存中的内容&#xff1a; 内存中存放了指令&#xff0c;每一个指令存放的地址不一样&#xff0c;所需的内存空间也不一样。 运算器能够进行算数运算和逻辑运算&#xff0c;这些运算在CPU中都是以运算电路的形式存在&#xff0c;一个运算功能对应一种运算电…

【Ant.designpro】上传图片

文章目录 一、前端二、后端 一、前端 fieldProps:可以监听并且获取到组件输入的内容 action{“/api/upload_image”} 直接调用后端接口 <ProFormUploadButtonlabel{"上传手续图片"}name{"imgs"}action{"/api/upload_image"}max{5} fieldPro…

CSS基础知识六(浮动的高度塌陷问题及解决方案)

目录 1.浮动高度塌陷概念 2.下面是几种解决高度塌陷的几种方案&#xff1a; 解决方案一&#xff1a; 解决方案二&#xff1a; 解决方案三&#xff1a; 1.浮动高度塌陷概念 在CSS中&#xff0c;高度塌陷问题指的是父元素没有正确地根据其内部的浮动元素或绝对定位元素来计…

【云原生开发】K8S集群管理后端开发设计与实现

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

计算机网络——SDN

分布式控制路由 集中式控制路由