当前位置: 首页 > news >正文

【c++11线程库的使用】

#include<iostream>
#include<thread>
#include<string>
using namespace std;
void hello(string msg) {
    for (int i = 0; i < 1000; i++) {
        cout << i;
        cout << endl;
    }
}
int main() {
    //1.创建线程
    thread thread1(hello,"hello Thread");//打印的就是hello Thread
    //主程序等待  看我这个程序运行完了吗
    //第三个知识点:thread1.join();//当上一个线程没有结束之前主线程是不会结束的
    //主线程结束之后我的线程依然可以再后台运行 那就是分离线程detach()
    //第四个知识点:thread1.detach();//这个就是主线程和子线程分离
    //第五个知识点:
    bool isJoin = thread1.joinable();//针对一个线程,可以调用detach,或者join。两者是互斥的关系,
    //也就说一旦调用了join,detach就不能再调用了,反之亦成立。
    //判断是否已经使用过join或者detach可以用joinable。
    if (isJoin) {
        thread1.join();
    }
    cout << "over" << endl;
    return 0;
}

std::ref传递引用类型

 #include<iostream>#include<thread>#include<string>using namespace std;void foo(int& x) {x += 1;}int main() {int a = 1;//thread t(foo, 1);//这个1不是引用是临时变量穿不进去  就释放掉了//所以要用ref  修饰这个a证明这个a就是它需要的引用变量thread t(foo, ref(a));t.join();cout << a << endl;return 0;}

类成员函数作为入口函数,类对象被提前释放

  错误示例:#include <iostream>#include <thread>​class MyClass {public:void func() {std::cout << "Thread " << std::this_thread::get_id() << " started" << std::endl;// do some workstd::cout << "Thread " << std::this_thread::get_id() //线程的信息<< " finished" << std::endl;}};​int main() {MyClass obj;std::thread t(&MyClass::func, &obj);// obj 被提前销毁了,会导致未定义的行为return 0;}

上面的代码中,在创建线程之后,obj 对象立即被销毁了,这会导致在线程执行时无法访问 obj 对象,可能会导致程序崩溃或者产生未定义的行为。

为了避免这个问题,可以使用 std::shared_ptr 来管理类对象的生命周期,确保在线程执行期间对象不会被销毁。具体来说,可以在创建线程之前,将类对象的指针封装在一个 std::shared_ptr 对象中,并将其作为参数传递给线程。这样,在线程执行期间,即使类对象的所有者释放了其所有权,std::shared_ptr 仍然会保持对象的生命周期,直到线程结束。

 #include<iostream>#include<thread>#include<string>#include<memory>using namespace std;class A {public:void foo() {cout << "hello world" << endl;;}};int main() {shared_ptr<A> a = make_shared<A>();//这个指针就是一直有效的//如果使用指针就还得手动释放内存  就很麻烦所以用智能指针//不需要这个变量的时候就释放掉thread t(&A::foo, a); // 这个指针就是一直有效的t.join();return 0;}

互斥量解决多线程数据共享问题

数据共享问题分析

在多个线程中共享数据时,需要注意线程安全问题。如果多个线程同时访问同一个变量,并且其中至少有一个线程对该变量进行了写操作,那么就会出现数据竞争问题。数据竞争可能会导致程序崩溃、产生未定义的结果,或者得到错误的结果。

为了避免数据竞争问题,需要使用同步机制来确保多个线程之间对共享数据的访问是安全的。常见的同步机制包括互斥量、条件变量、原子操作等。

 //这个就是互相抢夺资源的代码#include<iostream>#include<thread>#include<string>#include<memory>using namespace std;int a = 0;void foo() {for (int i = 0; i <= 10000; i++) {a += 1;}}int main() {thread t1(foo);thread t2(foo);​t1.join();t2.join();cout << a << endl;//输出17520  预期结果是20000 这就是互相抢夺资源了return 0;}

互斥锁解决

 #include<iostream>#include<thread>#include<string>#include<memory>#include<mutex>using namespace std;int a = 0;mutex mtx;void foo() {for (int i = 0; i < 10000; i++) {mtx.lock();//lock枷锁操作 如果不解锁其它线程是不能执行下面操作的a += 1;mtx.unlock();}}int main() {thread t1(foo);thread t2(foo);​t1.join();t2.join();cout << a << endl;//输出是20000 return 0;}

互斥量死锁

 //这就是死锁  死锁就是func_1在等着m2的所有权  func_2在等着m1的所有权  但是他俩都再互相等所以就没有释放彼此的锁就产生了死锁#include<iostream>#include<thread>#include<mutex>using namespace std;​mutex m1,m2;void func_1() {for (int i = 0; i < 50; i++) {m1.lock();m2.lock();m1.unlock();m2.unlock();​}}void func_2() {for (int i = 0; i < 50; i++) {m2.lock();m1.lock();m2.unlock();m1.unlock();​}}int main() {thread t1(func_1);thread t2(func_2);​t1.join();t2.join();cout << "over" << endl;return 0;}
lock_guard 与 std::unique_lock

lock_guard的特点:

  • 当构造函数被调用时,该互斥锁会被自动锁定

  • 当析构函数被调用时,该互斥锁会被自动解锁

  • lock_guard对象不能复制或移动,因此只能在局部作用域中使用

 #include<iostream>#include<thread>#include<string>#include<memory>#include<mutex>using namespace std;int a = 0;mutex mtx;void foo() {for (int i = 0; i < 10000; i++) {lock_guard<mutex>lg(mtx);a += 1;}}int main() {thread t1(foo);thread t2(foo);​t1.join();t2.join();cout << a << endl;//输出20000 return 0;}

unique_lock:

std:: 是 C++ 标准库中提供的一个互斥量封装类,用于在多线程程序中对互斥量进行加锁和解锁操作。它的主要特点是可以对互斥量进行更加灵活的管理,包括延迟加锁、条件变量、超时等。

std::unique_lock 提供了以下几个成员函数:

 `lock()`:尝试对互斥量进行加锁操作,如果当前互斥量已经被其他线程持有,则当前线程会被阻塞,直到互斥量被成功加锁。​`try_lock()`:尝试对互斥量进行加锁操作,如果当前互斥量已经被其他线程持有,则函数立即返回 `false`,否则返回 `true`。​`try_lock_for(const std::chrono::duration<Rep, Period>& rel_time)`:尝试对互斥量进行加锁操作,如果当前互斥量已经被其他线程持有,则当前线程会被阻塞,直到互斥量被成功加锁,或者超过了指定的时间。​`try_lock_until(const std::chrono::time_point<Clock, Duration>& abs_time)`:尝试对互斥量进行加锁操作,如果当前互斥量已经被其他线程持有,则当前线程会被阻塞,直到互斥量被成功加锁,或者超过了指定的时间点。​`unlock()`:对互斥量进行解锁操作。

单例设计模式

单例设计模式是一种常见的设计模式,用于确保某个类只能创建一个实例。由于单例实例是全局唯一的,因此在多线程环境中使用单例模式时,需要考虑线程安全的问题。

下面是一个简单的单例模式的实现:

 #include<iostream>#include<thread>#include<string>#include<memory>#include<mutex>using namespace std;​//日志功能就是单例模式 class Log {public:Log() {};Log(const Log& log) = delete;//在某些情况下,我们希望类的实例只能有一个。通过禁用拷贝构造函数,我们可以确保不会创建多个相同的实例。Log& operator = (const Log& log) = delete; ​static Log& GetInstance() {//这样写就是全局只有一个log不会有第二个这就是懒汉模式//提前构造了一个对象 需要的时候就返回这个对象static Log log;return log;/** static Log *log = nullptr;//饿汉模式* if(!log) log = new Log;* return *log;//提前不声明指针,需要的时候才创建对象*/}void PrintLog(string msg) {cout << msg << endl;​}};int main() {Log::GetInstance().PrintLog("error");return 0;}

call_once知识

多线程在单例模式中出现的一个问题:就是一下代码因为是单例模式但是线程调用两个线程是并行的 那就声明了两次

 ​#include<iostream>#include<thread>#include<string>#include<memory>#include<mutex>using namespace std;​//日志功能就是单例模式 class Log {public:Log() {};Log(const Log& log) = delete;Log& operator = (const Log& log) = delete; ​static Log& GetInstance() {//这样写就是全局只有一个log不会有第二个这就是懒汉模式//提前构造了一个对象 需要的时候就返回这个对象static Log log;return log;/** static Log *log = nullptr;//饿汉模式* if(!log) log = new Log;* return *log;//提前不声明指针,需要的时候才创建对象*/}void PrintLog(string msg) {cout << msg << endl;​}};void printError() {Log::GetInstance().PrintLog("error");}int main() {thread t1(printError);thread t2(printError);t1.join();t2.join();​return 0;}

我们就用call_once解决

 #include<iostream>#include<thread>#include<string>#include<memory>#include<mutex>using namespace std;​//日志功能就是单例模式 static Log* log = nullptr;//饿汉模式static once_flag once;class Log {public:Log() {};Log(const Log& log) = delete;Log& operator = (const Log& log) = delete; ​static Log& GetInstance() {//这样写就是全局只有一个log不会有第二个这就是懒汉模式提前构造了一个对象 需要的时候就返回这个对象//static Log log;//return log;if(!log) log = new Log;call_once(once, init);return *log;//提前不声明指针,需要的时候才创建对象}void PrintLog(string msg) {cout << msg << endl;​}static void init() {if (!log) log = new Log;}   };void printError() {Log::GetInstance().PrintLog("error");}int main() {thread t1(printError);thread t2(printError);t1.join();t2.join();​return 0;}

线程池的使用 写的

必要的东西:- 一个线程数组(维护一堆线程)
- 任务队列
- 用户 /生产者向队列里加任务
- 线程数组派线程取任务```
#include<iostream>
#include<thread>
#include<string>
#include<memory>
#include<mutex>
#include<condition_variable>
#include<queue>
#include<vector>
using namespace std;
#include<functional>
class ThreadPool {
public:ThreadPool(int numThreads) :stop(false) {for (int i = 0; i < numThreads; i++) {threads.emplace_back([this] {//添加任务  用了拉姆达表达式while (1) {unique_lock<mutex> lock(mtx);condition.wait(lock, [this] {//判断任务队列里面有没有任务 有就取return !tasks.empty() || stop;});if (stop && tasks.empty()) {return;}function<void()> task(move(tasks.front()));    tasks.pop();lock.unlock();task();}});}}~ThreadPool() {{unique_lock<mutex> lock(mtx);stop = true;//代表线程结束了}condition.notify_all();for (auto& t : threads) {//自动类型推导 自动判断这个数组里面是什么类型t.join();}}template<class F,class... Args>void enqueue(F &&f,Args&&... args) {function<void()> task =bind(forward<F>(f),forward<Args>(args)...);{unique_lock<mutex> lock(mtx);tasks.emplace(move(task));}condition.notify_one();}
private:vector<thread> threads;//线程数组queue<function<void()>> tasks;mutex mtx;condition_variable condition;//条件变量bool stop;//线程池什么时候终止};
int main() {ThreadPool pool(4);for (int i = 0; i < 10; i++) {pool.enqueue([i]() {cout << "第几个任务" << i << "任务开始" << endl;this_thread::sleep_for(chrono::seconds(1));cout << "第几个任务" << i << "任务结束" << endl;});}return 0;}```

相关文章:

【c++11线程库的使用】

#include<iostream> #include<thread> #include<string> using namespace std; void hello(string msg) { for (int i 0; i < 1000; i) { cout << i; cout << endl; } } int main() { //1.创建线程 thread …...

无限debugger的几种处理方式

不少网站会在代码中加入‘debugger’&#xff0c;使你F12时一直卡在debugger&#xff0c;这种措施会让新手朋友束手无策。 js中创建debugger的方式有很多&#xff0c;基础的形式有&#xff1a; ①直接创建debugger debugger; ②通过eval创建debugger&#xff08;在虚拟机中…...

数据库基础理论知识

1.基本概念 数据(Data)&#xff1a;数据库存储的基本对象。数字、字符串、图形、图像、音频、视频等数据库(DB)&#xff1a;在计算机内&#xff0c;永久存储、有组织、可共享的数据集合数据库管理系统(DBMS)&#xff1a;管理数据库的系统软件数据库系统(DBS):DBDBMSDBADBAP 数…...

华为OD机试真题-模拟目录管理-2024年OD统一考试(C卷)

题目描述: 实现一个模拟目录管理功能的软件,输入一个命令序列,输出最后一条命令运行结果。 支持命令: 1)创建目录命令:mkdir 目录名称,如mkdir abc为在当前目录创建abc目录,如果已存在同名目录则不执行任何操作。此命令无输出。 2)进入目录命令:cd 目录名称, 如cd …...

yield代码解释

目录 我们的post请求爬取百度翻译的代码 详细解释 解释一 解释二 再说一下callback 总结 发现了很多人对存在有yield的代码都不理解&#xff0c;那就来详细的解释一下 我们的post请求爬取百度翻译的代码 import scrapy import jsonclass TestpostSpider(scrapy.Spider):…...

C#四部曲(知识补充)

Unity跨平台原理 .Net相关 只要编写的时候遵循.NET的这些规则&#xff0c;就能在.NET平台下通用 各种源码→根据.NET规范编写→(虚拟机)生成CIL中间码(保存在程序集中)→转成操作系统原代码 跨语言← 跨平台↓ Unity跨平台原理&#xff08;Mono&#xff09; c#脚本→MonoC#编…...

Vue中的数据交互有几种方式

1. 单向数据流&#xff1a; Vue中的数据流是单向的&#xff0c;从父组件传递到子组件。父组件可以通过props将数据传递给子组件&#xff0c;子组件通过props接收并使用这些数据。这种方式适用于父子组件之间的简单通信。 2. 事件&#xff1a; 子组件可以通过触发自定义事件来…...

2.MySQL中的数据类型

整数类型&#xff1a; tinyint(m): 1个字节 范围(-128~127) 常用&#xff1a;性别 0和1表示性别&#xff1b;状态 0和1表示 int(m): 4个字节 范围(-2147483648~2147483647) 常用&#xff1a;数值 数值类型中的长度m是值显示长度&#xff0c;只有字段指定zerofill时有用 例如…...

身份证查询真伪-三要素查验-ios身份证实名认证接口调用

身份证实名认证接口联网核验是实名认证的关键一步&#xff0c;通过翔云OCR识别出的身份证信息&#xff0c;联网上传全国人口数据库&#xff0c;通过比对查找&#xff0c;确认人口数据库是否有身份证号和姓名匹配的信息&#xff0c;如果有那就确认身份证是真的&#xff0c;如果没…...

@EnableWebMvc介绍和使用详细demo

EnableWebMvc是什么 EnableWebMvc 是 Spring MVC 中的一个注解&#xff0c;它用于启用 Spring MVC 框架的基本功能&#xff0c;以便你可以使用 Spring MVC 提供的特性来处理 Web 请求。 通常情况下&#xff0c;在基于 Spring Boot 的应用中&#xff0c;并不需要显式地使用 Ena…...

VC-旅游系统-213-(代码+说明)

转载地址: http://www.3q2008.com/soft/search.asp?keyword旅游系统 旅游信息管理系统开题报告 一、研究目的 旅游信息管理系统能帮助旅行社在游客的市场开拓、游客的信息管理、客户服务等方面进行综合处理。使旅行社能够准确的掌握客户的市场动态&#xff0c;充分了解对客户…...

重学SpringBoot3-ErrorMvcAutoConfiguration类

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-ErrorMvcAutoConfiguration类 ErrorMvcAutoConfiguration类的作用工作原理定制 ErrorMvcAutoConfiguration示例代码1. 添加自定义错误页面2.自定义错误控…...

剑指offer面试题34 丑数

考察点 空间换时间提效知识点 题目 分析 这里面其实用到了一点点的数学知识&#xff0c;丑数的定义是只包含2&#xff0c;3&#xff0c;5因子的数。现在要求第1500个丑数&#xff0c;最简单的办法就是从数字1开始遍历&#xff0c;依次判断每个数字是不是丑数&#xff0c;如果…...

C++ std::list的merge()使用与分析

看到《C标准库第2版》对list::merge()的相关介绍&#xff0c;令我有点迷糊&#xff0c;特意敲代码验了一下不同情况的调用结果。 《C标准库第2版》对list::merge()的相关介绍 list::merge()定义 merge()的作用就是将两个list合并在一起&#xff0c;函数有2个版本&#xff1a;…...

Quartz的分布式功能化设计

Quartz的分布式功能化设计 文章目录 Quartz的分布式功能化设计主体功能实现依赖API例子JOBJob记录表设计java具体代码DateDOOperatorDOSysQuartzJobDOPageDTOQuartzJobDTOQuartzJobPageDTOQuartzJobStatusEnumQuartzJobControllerIQuartzJobServiceQuartzJobServiceImplQuartzJ…...

Caffeine缓存

本地缓存基于本地环境的内存&#xff0c;访问速度非常快&#xff0c;对于一些变更频率低、实时性要求低的数据&#xff0c;可以放在本地缓存中&#xff0c;提升访问速度 使用本地缓存能够减少和Redis类的远程缓存间的数据交互&#xff0c;减少网络 I/O 开销&#xff0c;降低这…...

AI辅助研发正在成为造福人类的新生科技力量

目录 1.AI用于药物研发 &#xff08;1&#xff09;药物靶点预测&#xff1a; &#xff08;2&#xff09;药物分子设计&#xff1a; &#xff08;3&#xff09;药物筛选&#xff1a; &#xff08;4&#xff09;药效和安全性预测&#xff1a; &#xff08;5&#xff09…...

程序分享--排序算法--归并排序

关注我&#xff0c;持续分享逻辑思维&管理思维&#xff1b; 可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导&#xff1b; 有意找工作的同学&#xff0c;请参考博主的原创&#xff1a;《面试官心得--面试前应该如何准备》&#xff0c;《面试官心得--面试时如何进行自…...

pg数据库和mysql区别

区别一 PostgreSQL (通常称为 PG) 和 MySQL 都是广泛使用的关系型数据库管理系统 (RDBMS)。虽然它们都是用于存储和管理数据的关系数据库&#xff0c;但它们在一些方面有很大的区别&#xff0c;如下所述&#xff1a; 数据类型&#xff1a;PostgreSQL 支持更多的数据类型&#…...

Jetpack Compose 动画正式开始学习

1. 简单值动画 //将一个Color简单值 从一个值 变化到另一个 另一个简单值 就用 animateColorAsStateval backgroundColor by animateColorAsState(if (tabPage TabPage.Home) Purple100 else Green300) 动画其实就是 一个状态不停发生改变导致 组件不断重组产生的过程 2.…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...