C++的线程

embedded/2024/9/25 7:54:34/
#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
void myrun()
{while(true){cout<<"I am a thread"<<endl;sleep(1);}
}
int main()
{thread t(myrun);t.join();return 0;
}

如果不添加-lpthread就会报错。 

用纯c++的接口创建线程时,在Linux中还是要包含线程库。

这说明c++的那些库本质就是pthread原生线程库的封装。

这样,我们学习别的语言,只需要学习接口,因为我们知道底层是一样的。

说到底,这样的设计就是为了跨平台性。

接下来了解一下线程的局部存储。

__thread可以给每个执行流一个变量。

在编译链接库时,就会给每一个变量在线程局部存储中开辟空间。

#include<iostream>
#include<thread>
#include<unistd.h>
using namespace std;
__thread int g_val=100;
void myrun()
{while(g_val--){cout<<"I am a new thread"<<"       "<<g_val<<"      "<<&g_val<<endl;sleep(1);}
}
int main()
{thread t(myrun);while(g_val--){cout<<"I am main thread"<<"       "<<g_val<<"      "<<&g_val<<endl;sleep(2);}t.join();return 0;
}

下面是多线程的一个简单模版。 

//test.hpp
#include<iostream>
#include<thread>
#include<unistd.h>
#include<functional>
#include<vector>
using namespace std;
template<class T>
using func_t=function<void(T)>;//返回值为void,参数为T
template<class T>
class Thread
{public:Thread(func_t<T> func,const string&name,T data):_tid(0),_func(func),_threadname(name),isrunning(false),_data(data){}static void*ThreadRoutine(void*args){//(void)args;//仅仅是为了防止编译器有告警Thread*ts=static_cast<Thread*>(args);ts->_func(ts->_data);return nullptr;}bool Start(){int n=pthread_create(&_tid,nullptr,ThreadRoutine,this);if(n==0){isrunning=true;return true;}return false;}bool Join(){if(!isrunning) return true;int n=pthread_join(_tid,nullptr);if(n==0){isrunning=false;return true;}return false;}string GetThreadName(){return _threadname;}bool IsRunning(){return isrunning;}~Thread(){}private:pthread_t _tid;string _threadname;bool isrunning;func_t<T> _func;T _data;
};
#include"test.hpp"
using namespace std;
string GetThreadName()
{static int number=1;char name[64];snprintf(name,sizeof name,"Thread - %d",number++);return name;
}
void print(int num)
{while(num--){cout<<"hello world"<<num<<endl;sleep(1);}
}
int main()
{int num=5;vector<Thread<int>> Threads;while(num--){Threads.push_back(Thread<int>(print,GetThreadName(),10));}for(auto &t:Threads){cout<<t.GetThreadName()<<" is running? "<<t.IsRunning()<<endl;}for(auto&t:Threads){t.Start();}for(auto &t:Threads){cout<<t.GetThreadName()<<" is running? "<<t.IsRunning()<<endl;}for(auto &t:Threads){t.Join();}// Thread t(print,GetThreadName());// cout<<"Is thread running?"<<t.IsRunning()<<endl;// t.Start();// cout<<"Is thread running?"<<t.IsRunning()<<endl;// t.Join();return 0;
}

 

 


http://www.ppmy.cn/embedded/15470.html

相关文章

深入探讨负载均衡的原理及算法

在现代分布式系统中,负载均衡扮演着至关重要的角色。随着用户数量和流量的不断增长,单个服务器已经无法承担巨大的负载。因此,需要将负载分散到多个服务器上,以确保系统的高可用性、可扩展性和响应能力。负载均衡不仅可以提高系统的整体性能,还能够实现故障转移和灾难恢复,从而…

统一建模语言UML图

uml 图定义 Unified Modeling Language&#xff08;统一建模语言&#xff0c;UML&#xff09;是一种用于软件系统设计和建模的标准化语言。它提供了一套图形化的符号和约定&#xff0c;用于描述软件系统的结构、行为和交互&#xff0c;以及系统与外部环境之间的关系。UML通常用…

天人、人间、二神之间的宗教战争

文本&#xff1a;创世记 2-3、马太福音 23-24、启示录 12-13  天人、地球人和两位神之间的宗教战争是什么样的&#xff1f;  属天的&#xff08;天体&#xff09;是神&#xff08;创世记6&#xff09;&#xff0c;属地的&#xff08;地上的人&#xff09;是肉身。有两个主要的…

BERT论文阅读

一.前情提要 1.本文理论为主&#xff0c;并且仅为个人理解&#xff0c;能力一般&#xff0c;不喜勿喷 2.本文理论知识较为成体系 3.如有需要&#xff0c;以下是原文&#xff0c;更为完备 BERT 论文逐段精读【论文精读】_哔哩哔哩_bilibili 二.正文 1.前言&#xff1a; ①…

VSCode配置Springboot开发环境

VSCode配置Springboot开发环境 一、下载和安装JDK一、pandas是什么&#xff1f;二、下载和安装Maven三、VSCode配置3.1 插件管理3.2 VSCode中的Maven配置3.3 创建项目3.4 VSCode中打包springboot项目3.5 springboot项目发布服务后&#xff0c;前端跨域问题&#xff1a; 四、VSC…

C++智能指针

智能指针 1. 异常导致的内存泄露2. 智能指针的使用及原理2.1 RAII 3. 库里面的智能指针3.1 std::auto_ptr3.2 std::unique_ptr3.3 std::shared_ptr3.3.1shared_ptr的缺陷——循环引用3.3.2 weak_ptr 1. 异常导致的内存泄露 在我们异常那块章节中&#xff0c;我们有提到如果异常…

【设计模式】9、facade 外观模式

文章目录 九、外观模式9.1 player9.1.1 player_test.go9.1.2 player.go 9.2 login_register9.2.1 account_test.go9.2.2 account.go 九、外观模式 https://refactoringguru.cn/design-patterns/facade 如果有一个复杂的系统, 内部有很多子系统, 可以用 facade 封装一层, 只暴…

【汇编语言】流程转移和子程序

【汇编语言】流程转移和子程序 文章目录 【汇编语言】流程转移和子程序前言一、“转移”综述二、操作符offset三、jmp指令jmp指令——无条件转移jmp指令&#xff1a;依据位移进行转移两种段内转移远转移&#xff1a;jmp far ptr 标号转移地址在寄存器中的jmp指令转移地址在内存…