C++学习(线程相关)

目录

一、线程库thread

1.使用外部函数

2. 使用类的函数

3. 添加参数

二、线程库 mutex

1.使用lock()方法

2.try_lock()方法

三、线程库lock_guard

四、线程库unique_lock

1.adopt_lock

2.defer_lock()

五、线程库call_once

六、线程库promise & future

七、condition变量使用场景

八、async 和 packaged_task

1.async

2.packaged_task


一、线程库thread

1.使用外部函数

        下面这段代码的目的是等待子线程运行结束,因为可能存在主线程已经结束了,但是子线程还有程序要运行,此时直接return可能会出问题。

    t1.join();

2. 使用类的函数

#include<iostream>
#include<chrono>
#include<thread>
using namespace std;int i = 0;
void test1()
{while(i< 10){cout << "子线程运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}
}
class A
{private:int i = 0;public:void test2(){while(i< 10){cout << "子线程运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}}
};int main()
{A a;thread t1(&A::test2, &a);while(i< 10){cout << "主线程运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

3. 添加参数

#include<iostream>
#include<chrono>
#include<thread>
using namespace std;
int i = 0;
class A
{private:int i = 0;public:void test2(int num){while(i< 10){cout << "子线程运行中:num:" << num << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}}
};int main()
{A a;thread t1(&A::test2, &a, 100);while(i< 10){cout << "主线程运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

二、线程库 mutex

对于上面第一个的例子,存在主线程或者子线程打印一半,时间片结束,进入另外一个线程打印,导致乱码,为了解决这个问题,引入锁。

1.使用lock()方法

使用lock加锁之后,当子线程执行一般,此时还没释放锁,进入主线程,主线程也调用lock(),发现锁已经被占用了,于是就等待,之后时间片到了进入子线程,子线程程序执行完毕后释放锁unlock()。

2.try_lock()方法

这个方法尝试获取锁,成功获得返回true,否则返回false,他不会阻塞,获取不到锁也可以做一些其他操作。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
using namespace std;
int i = 0;
mutex mtx;
void test2()
{while(i< 10){if(mtx.try_lock()){cout << "子线程运行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10000));i++;mtx.unlock();}else{cout << "子线程等待中:"<< endl;}}
}
int main()
{thread t1(test2);while(i< 10){if(mtx.try_lock()){cout << "主线程运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10000));mtx.unlock();}else{cout << "主线程等待中:"<< endl;}}t1.join();return 0;
}

三、线程库lock_guard

上面每次都需要手动释放,可能存在忘了释放锁,就会有bug,下面解决这个问题。本质上当这个变量作用域结束的时候执行析构函数,自动释放锁。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<sstream>
using namespace std;int i = 0;
mutex mtx;// 辅助函数,用于获取线程 ID 字符串
string getThreadId() {stringstream ss;ss << this_thread::get_id();return ss.str();
}void test2()
{while(i < 10){lock_guard<mutex> lock(mtx);cout << "子线程 " << getThreadId() << " 运行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}
}int main()
{thread t1(test2);while(i < 10){lock_guard<mutex> lock(mtx);cout << "主线程 " << getThreadId() << " 运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

四、线程库unique_lock

unique_lock提供了更高级的用法。它可以多传一个参数,也可以不传,不穿的用法和lock_guard一样。

1.adopt_lock

它的作用是接管锁,上面先创建一个锁,之后由他接管,作用域结束的时候自动释放。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<sstream>
using namespace std;int i = 0;
mutex mtx;// 辅助函数,用于获取线程 ID 字符串
string getThreadId() {stringstream ss;ss << this_thread::get_id();return ss.str();
}void test2()
{while(i < 10){mtx.lock();unique_lock<mutex> lock(mtx, adopt_lock);cout << "子线程 " << getThreadId() << " 运行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}
}int main()
{thread t1(test2);while(i < 10){mtx.lock();unique_lock<mutex> lock(mtx, adopt_lock);cout << "主线程 " << getThreadId() << " 运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

2.defer_lock()

defer_lock的作用是延迟锁,在后面调用lock.lock();才会获取锁和加锁。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<sstream>
using namespace std;int i = 0;
mutex mtx;// 辅助函数,用于获取线程 ID 字符串
string getThreadId() {stringstream ss;ss << this_thread::get_id();return ss.str();
}void test2()
{while(i < 10){unique_lock<mutex> lock(mtx, defer_lock);lock.lock();cout << "子线程 " << getThreadId() << " 运行中:" << i << endl;this_thread::sleep_for(chrono::microseconds(10));i++;}
}int main()
{thread t1(test2);while(i < 10){unique_lock<mutex> lock(mtx, defer_lock);lock.lock();cout << "主线程 " << getThreadId() << " 运行中:" << i << endl;i++;this_thread::sleep_for(chrono::microseconds(10));}t1.join();return 0;
}

五、线程库call_once

        如果存在好几个线程,调用一个函数,这个函数里面有个初始化操作,这个操作只需要被执行一次,就会用到下面的操作。

        声明once_flag, 之后将once_flag,init函数和以及init函数的参数传递给call_once。

六、线程库promise & future

这个主要作用是异步获取线程函数里面的数据。int sum = ft.get();这段代码会阻塞,直到子线程设置ps.set_value(sum);。注意使用future<int> ft = ps.get_future();声明的话,主线程只能get一次,如果想要get多次,那么使用shared_future<int> ft = ps.get_future();。

七、condition变量使用场景

        生产者消费者模型,生产者不断往队列中添加任务,之后通知消费者取任务。

关键代码解释

cv.notify_one();   // 通知另外一个线程取任务

cv.wait(lck, []{return !q.empty();});    //  这个锁的参数很有必要,因为上面给锁住了,所以需要先释放了锁才行,所以锁也需要作为参数传入,后面的就是条件,如果为True就等待。

#include<iostream>
#include<chrono>
#include<thread>
#include<mutex>
#include<queue>
#include<condition_variable>
using namespace std;queue<int> q;
condition_variable cv;
mutex mtx;
void Product()
{for(int i=0; i<10; i++){{unique_lock<mutex> lck(mtx);q.push(i);cv.notify_one();cout << "生产了" << i << endl << flush; }this_thread::sleep_for(chrono::milliseconds(5)); // 延长时间}
}void Consumer()
{while(true){unique_lock<mutex> lck(mtx);cv.wait(lck, []{return !q.empty();});int data = q.front();q.pop();cout << "消费了" << data << ",队列大小: " << q.size() << endl << flush;if(data == -1) break;  // 正确退出this_thread::sleep_for(chrono::milliseconds(3)); }
}
void test2()
{   thread t2(Consumer);thread t1(Product);t1.join();// 添加退出条件,避免消费者线程无限循环{unique_lock<mutex> lck(mtx);q.push(-1); // 发送结束信号cv.notify_one();}t2.join();
}int main()
{test2();return 0;
}

八、async 和 packaged_task

他俩的作用都是异步获取函数返回值。

1.async

关键代码解释:

future<int> f = async(add);    // 自动产生一个线程执行add这个函数

f.get()  // 读取函数的返回值

2.packaged_task

关键代码解释:

packaged_task<int()> task(add);      // 创建一个packaged_task对象,不会创建线程

auto future_result = task.get_future();    // 得到这个任务的future对象

thread t(move(task));      // 根据任务创建线程,开始这行任务里面的函数

cout<<"sum = "<<future_result.get()<<endl;   // 等待函数执行完成,获得返回值,对于future的get方法,如果函数没有执行完成,就会阻塞。

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

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

相关文章

EPOLLONESHOT 深度解析:Linux epoll 的单次触发机制

EPOLLONESHOT 深度解析&#xff1a;Linux epoll 的单次触发机制 EPOLLONESHOT 是 Linux epoll 接口中的高级事件标志&#xff0c;用于实现精确的事件单次触发控制。以下是其全面技术解析&#xff1a; 核心设计理念 #mermaid-svg-Xg5sCLdddqmKsvKG {font-family:"trebuchet…

深入解析MongoDB分片原理与运维实践指南

深入解析MongoDB分片原理与运维实践指南 技术背景与应用场景 随着互联网业务的高速发展&#xff0c;单节点MongoDB实例在数据量和访问并发上都面临瓶颈。为了解决数据存储容量受限和读写性能下降的问题&#xff0c;MongoDB官方提供了分片&#xff08;Sharding&#xff09;方案&…

基于Django的天气数据可视化分析预测系统

【86-Django】基于Django的天气数据可视化分析预测系统&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介 二、项目界面展示 三、项目视频展示 四、技术架构 五、核心功能模块 六、部署教程一、项目简介 随着全球气候变化和极端天气事件的频发&am…

怎么放大单片机输出电流

单片机作为电子系统的控制核心&#xff0c;其 I/O 口输出电流通常较小&#xff08;一般在 10-20mA 左右&#xff09;&#xff0c;难以直接驱动继电器、电机、大功率 LED 等需要较大工作电流的外设。因此&#xff0c;在实际应用中需通过特定电路放大单片机输出电流&#xff0c;实…

站长百科类网站pbootcms模板(自适应手机端)+利于SEO优化(下载)

站长百科类网站pbootcms模板(自适应手机端)利于SEO优化 模板介绍&#xff1a; PbootCMS内核开发的模板&#xff0c;该模板属于新闻资讯、新闻博客类企业使用&#xff01; 页面简洁简单&#xff0c;容易管理&#xff0c;附带测试数据&#xff01; 模板特点&#xff1a; 1、手工书…

【Golang】Go语言函数

Go语言函数 文章目录Go语言函数Go函数特点一、函数的基本格式定义二、匿名函数三、自执行函数四、闭包函数五、延迟调用Go函数特点 无需声明原型支持不定 变参支持多返回值支持匿名函数和闭包函数也是一种类型&#xff0c;一个函数可以赋值给变量不支持嵌套&#xff0c;一个包…

JAVA算法练习题day2

双指针4.移动零二刷昨天的题&#xff0c;学习了新的数据结构StringBuilder。专为频繁字符串拼接设计的可变字符串类。(https://blog.csdn.net/m0_73941339/article/details/145651287)二刷完昨天的题目&#xff0c;做到这题脑子已经转不动了。做双指针&#xff0c;一般双指针初…

LLM2Rec-新国立-KDD2025-微调LLM获得蕴含协同信息的embedding

文章目录1. 背景与问题任务背景动机LLM2Rec 两大步骤2. 方法2.1 Collaborative Supervised Fine-tuning&#xff08;CSFT&#xff09;2.2 Item-level Embedding Modeling2.2.1 从单向注意力 → 双向注意力&#xff08;Bidirectional attention&#xff09;2.2.2 商品级别的对比…

前端学习9:JavaScript--对象与原型

前言&#xff1a;适合有基础的同学入门尝试 / 复习回忆。对象基础&#xff1a;1.创建用户对象const user {// 属性&#xff08;键值对&#xff09;name: "小岛",age: 20,isAdmin: false, }2.方法&#xff08;函数属性&#xff09;sayHello() {console.log(你好&…

网络:应用层

网络&#xff1a;应用层 我们要知道&#xff0c;所有的问题解决都是在应用层。:happy: 协议是一种约定&#xff0c;也就是双方约定好的结构化的数据。但是在读写数据时我们都是按字符串的方式来发送接受的&#xff0c;那么我们应该如和传输结构化的数据呢&#xff1f;应用层协…

rust-包和箱子

&#x1f4e6; 图解 Rust 代码组织层级 #mermaid-svg-fBDy1PDZZ6bi000z {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-fBDy1PDZZ6bi000z .error-icon{fill:#552222;}#mermaid-svg-fBDy1PDZZ6bi000z .error-text{fi…

C++算法竞赛篇(五)循环嵌套题型讲解

C算法竞赛篇&#xff08;五&#xff09;循环嵌套题型讲解前言C循环嵌套题型讲解第一题 包含数字的9第二题 求出 e 的值第三题 斐波那契数列第四题 第 n 小的质数第五题 水仙花数前言 前面的题型里我们认识了C里面的三大循环本篇博客我们开始讲解C循环嵌套题型 我的个人主页&am…

Gradio全解8——ChatInterfaceChatbot:聊天界面类与聊天机器人(3)——ChatInterface的多模态功能与附加输入输出

Gradio全解8——ChatInterface&Chatbot&#xff1a;聊天界面类与聊天机器人&#xff08;3&#xff09;——ChatInterface的多模态功能与附加输入输出8.3 ChatInterface的多模态功能与附加输入输出8.3.1 多模态功能1. 设置multimodal和fn参数2. 传入MultimodalTextbox组件及…

php算法-- 关联数组使用,优化sip账号去重

文章目录1 变量定义2. 核心特性code1 变量定义 类型&#xff1a;嵌套的关联数组&#xff08;Nested Associative Array&#xff09;外层结构&#xff1a;[中继ID > 账号列表]键 (Key)&#xff1a;中继ID&#xff08;字符串或整型&#xff09;值 (Value)&#xff1a;索引数组…

LLM 多语言数据集

多语言数据感觉主要还是fineweb和fineweb2, 其他数据都是主要针对特定语种比较多 101 Billion Arabic Words Dataset ClusterlabAi/101_billion_arabic_words_dataset 数据主要从e Common Crawl WET 中提取&#xff0c;并采用了创新的技术来进行去重和筛选&#xff0c;主要解决…

【HarmonyOS Next之旅】DevEco Studio使用指南(三十六) -> 配置构建(三)

目录 1 -> 定制HAR多目标构建产物 1.1 -> 定义产物的deviceType 1.2 -> 定义C工程依赖的.so文件 1.3 -> 定义产物的资源 2 -> 配置APP多目标构建产物 2.1 -> 定义产物的APP包名和供应商名称 2.2 -> 定义product的bundleName 2.3 -> 定义produc…

数据赋能(340)——技术平台——共享平台

概述重要性如下&#xff1a;提高数据利用效率&#xff1a;数据共享平台能够将分散在各部门的数据进行集中管理&#xff0c;促进数据流通和共享&#xff0c;避免数据孤岛现象&#xff0c;从而提高数据利用效率。促进决策科学化&#xff1a;通过共享平台&#xff0c;各部门可以获…

开闭原则在C++中的实现

开闭原则&#xff08;Open/Closed Principle&#xff0c;简称 OCP&#xff09;是面向对象设计中的一个重要原则&#xff0c;属于“SOLID”原则之一。它的核心思想是&#xff1a;“软件实体&#xff08;如类、模块、函数等&#xff09;应该对扩展开放&#xff0c;对修改关闭。”…

C语言:*p++与p++有何区别

1. 指针基础练习&#xff1a;演示p、p和(*p)的区别核心目的&#xff1a;区分指针自增与指针指向值自增的不同逻辑&#xff0c;理解运算符优先级对指针操作的影响。#include <stdio.h>void arr1() {int arr[] {11,13,15,17,19};int *p arr;printf("结果1&#xff1…

【设计】设计一个web版的数据库管理平台后端(之二)

在之前&#xff0c;我写过一篇【设计】设计一个web版的数据库管理平台后端精要 的文章&#xff0c;文章讲了一个web版数据库管理平台的实现思路及主要代码。 最近&#xff0c;我看了下Mybatis的源码&#xff0c;觉得Mybatis的分层架构挺好&#xff0c;所以想到了完善下web版数据…