Linux--线程的分离、线程库的地址关系的理解、线程的简单封装(二)

线程系列:
线程的认识:讲解线程的概念和线程的基本控制

线程的分离

线程分离是指将一个线程从主线程中分离出来,使其能够独立运行。当一个线程被设置为分离状态时,它结束时系统会自动回收其资源,而不需要其他线程使用pthread_join()函数来等待其结束并手动回收资源。

设置线程分离的方法
使用pthread_detach()函数:在线程创建后,可以通过调用pthread_detach()函数来将线程设置为分离状态。这个函数是非阻塞式的,即调用后不会阻塞当前线程的执行。
在创建线程时设置分离属性:另一种方法是在创建线程时,通过pthread_create()函数的第二个参数(线程属性)来设置线程为分离状态。这种方法在创建线程时即指定了其分离属性,效率相对较高。

void* threadrun(void* args)
{string name = static_cast<const char *>(args);while(true){sleep(1);cout<<"this is new thread:"<<name<<endl;}
}
int main()
{pthread_t tid;pthread_create(&tid, nullptr, threadrun, (void *)"thread 1");cout << "main thread wait block" << std::endl;pthread_join(tid, nullptr);cout << "main thread wait return"<<endl;
}

在这里插入图片描述

使用分离函数后:
在这里插入图片描述

再加个有限时间的循环看看:
在这里插入图片描述
对线程分离理解虽然新线程与主线程已经分离了,但它们仍然是同一进程中的执行流,如果程序使用时出现异常时(新线程或者主线程),那么两个程序都会终止;或者说主线程结束了,实际上就代表进程结束了;所以线程的分离仍然是在进程中进行的,受进程的影响

何时使用:当线程完成任务后不需要与其结果交付时;当线程在后台运行且不需要与主线程进行同步进行时;

注意:分离线程无法重新连接!而可连接线程可以分离,当只有在尚未开始运行之前

理解线程库的地址关系

在这里插入图片描述

在这里插入图片描述

线程栈

线程栈是与线程紧密相关的内存区域,用于存储线程的局部变量、函数调用的返回地址以及线程的执行上下文等信息每个线程都有自己独立的栈空间,这保证了线程之间的数据是隔离的,从而避免数据竞争和线程安全问题。

#include<iostream>
using namespace std;
#include<pthread.h>
#include<unistd.h>
void *threadrun1(void *args)
{  std::string name = static_cast<const char *>(args);int g_val=100;while(true){sleep(1);printf("%s, g_val: %lu, &g_val: %p\n", name.c_str(), g_val--, &g_val);}return nullptr;
}void *threadrun2(void *args)
{std::string name = static_cast<const char *>(args);int g_val=100;while(true){printf("%s, g_val: %lu, &g_val: %p\n", name.c_str(), g_val--, &g_val);sleep(1);}return nullptr;
}int main()
{pthread_t tid1;pthread_t tid2;pthread_create(&tid1, nullptr, threadrun1, (void *)"thread 1");pthread_create(&tid2, nullptr, threadrun2, (void *)"thread 2");pthread_join(tid1, nullptr);pthread_join(tid2, nullptr);
}

通过两个新线程都创建一个局部变量(变量名相同),比较它们的地址;
在这里插入图片描述
可以看到g_val在各自线程是不一样的,地址也是不同的;

线程局部存储(TLS)

线程局部存储(TLS)是一种机制,允许每个线程拥有自己的私有数据副本,即使不同线程执行相同的代码,TLS变量与常规全局变量是不同的,因为每个线程堆TLS变量的访问都是独立的。

一般适用于:

  • 线程特定数据:当某些数据只对特定线程有意义,并且需要在线程内保持状态时,可以使用线程局部存储。
  • 全局状态隔离:通过将全局状态分离为每个线程的私有副本,可以提高并发性能,避免线程间的数据竞争。
  • 线程上下文保存:线程局部存储也可用于保存当前执行线程的上下文信息,如用户身份验证信息、数据库连接等。

注意:

线程局部存储变量通常只能用于具有静态或线程存储期的变量,不能用于自动或动态分配的变量。使用线程局部存储时需要谨慎管理内存,避免内存泄漏或无效访问等问题。

线程的封装

线程的封装通常指的是将线程的创建、执行、同步、资源管理等逻辑封装到一个类或对象中,以便更好地组织代码,提高代码的可读性和可维护性

封装线程可以隐藏线程的复杂性,使得其他部分的代码可以更加简洁地与线程进行交互。

下面看具体代码:

Thread.hpp:对线程的封装

#ifndef __THREAD_HPP__
#define __THREAD_HPP__#include<iostream>
#include<string>
#include<pthread.h>
#include<functional>
#include<unistd.h>using namespace std;namespace ThreadMdule
{//通过模板类可调用一切任何对象template<typename T>using func_t = std::function<void(T&)>;template<typename T>class Thread{public:void Excute(){_func(_data);}Thread(func_t<T> func, T data, const std::string &name="none-name"): _func(func), _data(data), _threadname(name), _stop(true){}static void* threadroutine(void* args){Thread<T>* self=static_cast<Thread<T>*>(args);self->Excute();return nullptr;}bool start(){int n=pthread_create(&_tid,nullptr,threadroutine,this);if(!n){_stop = false;return true;}else{return false;}}void Detach(){if(!_stop){pthread_detach(_tid);}}void Join(){if(!_stop){pthread_join(_tid,nullptr);}}string name(){return _threadname;}void Stop(){_stop = true;}~Thread() {}private:pthread_t _tid;std::string _threadname;T _data;  func_t<T> _func;bool _stop;};
}#endif

线程类中包括了:线程名,数据,调用函数指针等;
通过start()函数来创建新线程:用到了函数threadroutinue,在函数中将函数成员_func(也就是具体函数的指针)使用了起来,就表示新线程的创建使用;

主函数的调用:

void print(int &cnt)
{while (cnt){std::cout << "hello I am myself thread, cnt: " << cnt-- << std::endl;sleep(1);}
}const int num=3;
int main()
{vector<Thread<int>> threads;//创建新线程for(int i=0;i<num;i++){string name="thread"+to_string(i + 1);threads.emplace_back(print,3,name);}//启动进程for(auto& thread:threads){thread.start();}//等待进程结束for(auto& thread:threads){thread.Join();cout<<"wait thread done,thread is: "<<thread.name()<<endl;}return 0;
}

在这里插入图片描述
这样就是对线程的简单封装;

通过封装线程,我们可以更好地控制线程的创建、执行和销毁过程,同时使得代码更加清晰和易于维护。

此外,封装还可以帮助我们添加额外的功能,比如线程池的集成、异常处理、线程同步等。

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

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

相关文章

ArcGIS空间数据处理、空间分析与制图;PLUS模型和InVEST模型的原理,参量提取与模型运行及结果分析;土地利用时空变化以及对生态系统服务的影响分析

工业革命以来&#xff0c;社会生产力迅速提高&#xff0c;人类活动频繁&#xff0c;此外人口与日俱增对土地的需求与改造更加强烈&#xff0c;人-地关系日益紧张。此外&#xff0c;土地资源的不合理开发利用更是造成了水土流失、植被退化、水资源短缺、区域气候变化、生物多样性…

北京大学第一医院与智源研究院共同发布基于可信执行环境的AI医学影像挑战赛

肾动脉狭窄是导致继发性高血压及肾功能不全的常见原因&#xff0c;而目前针对肾动脉狭窄功能学的评估尚处于探索阶段。数据保护和可信计算环境是目前人工智能技术应用于临床研究的一大瓶颈。北京大学第一医院与北京智源人工智能研究院心脏AI 联合研究中心特发布基于可信执行环境…

Ubuntu22.04之解决:Flameshot无法截图问题(二百三十五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Ant design vue的表格双击编辑功能(即双击开始编辑并自动获得焦点,失去焦点时完成编辑)

本文基于Ant Design Vue官方网站的表格&#xff08;可编辑单元格&#xff09;&#xff08;表格 Table - Ant Design Vue (antdv.com))中的样板代码获得双击编辑且获得焦点、失去焦点时完成编辑的功能。 要点&#xff1a; &#xff08;1&#xff09;双击时候实现编辑&#xff…

如何使用Cloudways搭建WordPress网站(附最新Cloudways优惠码)

如今&#xff0c;搭建网站已经变得非常简单&#xff0c;这主要得益于开源的CMS建站系统的兴起。即使是不懂编程的人也能轻松搭建自己的网站&#xff0c;这些CMS系统提供了丰富的主题模板和插件&#xff0c;使用户可以通过简单的拖放和配置操作来建立自己的网站。 WordPress是目…

子网划分案例

4.2子网划分 “有类编址”的地址划分过于死板&#xff0c;划分的颗粒度太大&#xff0c;会有大量的主机号不能被充分利用&#xff0c;从而造成了大量的IP地址资源浪费。因此可以利用子网划分来减少地址浪费&#xff0c;即VLSM (Variable Length Subnet Mask)&#xff0c;可变长…

国内前十款专业外盘期货交易app软件排名盘点(综合版)

随着社会经济的不断发展&#xff0c;现在投资者倾向于投资各种项目以获取超额收益。在选择外盘期货交易app软件时&#xff0c;有几个关键的因素需要考虑。首先是软件的可靠度和安全度&#xff0c;因为交易涉及到实际资金。因此&#xff0c;需要选择具备专业资质、经验丰富、充分…

Android下HWC以及drm_hwcomposer普法(上)

Android下HWC以及drm_hwcomposer普法(上) 引言 按摩得全套&#xff0c;错了&#xff0c;做事情得全套&#xff0c;普法分析也是如此。drm_hwcomposer如果对Android图形栈有一定研究的童鞋们应该知道它是Android提供的一个的图形后端合成处理HAL模块的实现。但是在分析这个之前…

汽车悬架分为哪几类

汽车悬架分为哪几类 1)汽车的悬架系统可根据结构分为两种:独立悬架和非独立悬架,独立悬架根据构造又可以分为CDC运动悬架(CDC电磁悬架系统)和空气悬架; 2)当前比较火热的空气悬架,是独立悬架的一种; 3)前轮主要使用麦弗逊式独立悬架 和 双叉臂悬架,后轮主要使用多…

倒角距离【Chamfer Distance】

倒角距离&#xff08;chamfer distance&#xff09;是用于评估两组点之间的相似度的度量。给定两个点集 A 和 B&#xff0c;倒角距离定义为 A 中每个点到 B 中最近邻点的距离之和&#xff0c;加上 B 中每个点到 A 中最近邻点的距离之和。它用于各种应用&#xff0c;包括计算机视…

每期一个小窍门 k8s版本的 Prometheus + grafana + alertmanager 三件套部署监控落地

首先部署prometheus 首先是pvc apiVersion: v1 kind: PersistentVolumeClaim metadata:name: prometheus-data-pvcnamespace: monitor spec:accessModes:- ReadWriteManystorageClassName: "data-nfs-storage"resources:requests:storage: 10Gi然后接着 cluster-ro…

CSS+Canvas绘制最美星空(一闪一闪亮晶晶效果+流星划过)

1.效果 2.代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>body,html {margin: 0;padding: 0;ov…

20 VUE学习:插件

介绍 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。下面是如何安装一个插件的示例&#xff1a; import { createApp } from vueconst app createApp({})app.use(myPlugin, {/* 可选的选项 */ })一个插件可以是一个拥有 install() 方法的对象&#xff0c;也可以直接…

CNAS软件测试公司作用分享,如何获取CNAS软件测试报告?

在软件测试行业&#xff0c;CNAS认可和CNAS软件测试公司是不可忽视的关键词。CNAS认可是指中国合格评定国家认可委员会对特定领域组织、机构或公司的能力和资质进行的认可过程。该认可遵循国际标准及相关法律法规&#xff0c;是评定组织或实验室技术能力和专业水平的权威认可&a…

【考研数学】李艳芳900比李林880难吗?值得做吗?

差不多&#xff0c;只能说基础没搞好刷这两个都很费劲 李艳芳900题把每个章节题目划分为ABC三个难度级别&#xff0c;题目选取的难度较大也比较新颖&#xff0c;计算量也非常接近考研趋势&#xff0c;原创性很高&#xff0c;比较适合过完一轮的同学继续做补充和强化 880算是比…

Java 数组的基本使用【Array】

目录 含义语法格式语句特点数组的长度数组的元素打印数组显示数组数组的复制扩展示例【12】 含义 数组&#xff08;array&#xff09;是一种最简单的复合数据类型&#xff0c;它是有序数据的集合&#xff0c;数组中的每个元素具有相同的数据类型&#xff0c;可以用一个统一的数…

cesium绘制编辑区域

npm 安装也是可以的 #默认安装最新的 yarn add cesium#卸载插件 yarn remove cesium#安装指定版本的 yarn add cesium1.96.0#安装指定版本到测试环境 yarn add cesium1.96.0 -D yarn install turf/turf token记得换成您自己的&#xff01;&#xff01;&#xff01; <t…

如何培养元技能?

如何培养元技能&#xff1f; 一、引言 在当今社会&#xff0c;仅仅依靠某一专业技能是远远不够的。我们需要拓宽自己的能力和视野&#xff0c;从而更好地应对日新月异的社会发展和工作需求。在这个过程中&#xff0c;培养元技能变得至关重要。元技能不仅有助于我们在各个领域中…

【全开源】驾校管理系统源码(FastAdmin+ThinkPHP)

一款基于FastAdminThinkPHP开发的驾校管理系统&#xff0c;驾校管理系统(DSS)主要面向驾驶学校实现内部信息化管理&#xff0c;让驾校管理者和工作人员更高效、更快捷的完成枯燥无味的工作&#xff0c;让工作更有条理。改变驾校传统的手工或半手工Excel文档管理的工作方式。多驾…

嵌入式进阶——HID协议

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 USB烧录USB HID协议USB协议组成通讯流程 官方USB HID范例文件说明修改PC端的显示 兼容库函数HID键盘USB调试工具USB 描述符设备描述…