【C++11新特性】| 并发编程

news2024/11/15 21:32:39

文章目录

    • 一、std::thread
      • 1.1 成员函数
      • 1.2 案例
    • 二、std::mutex
    • 三、std::lock
      • 3.1 lock_guard
      • 3.2 unique_lock
      • 3.3 lock_guard与unique_lock的对比
    • 四、std::atomic
    • 五、volatile
    • 六、condition_variable
      • 成员函数
    • 七、future、promise、packaged_task
      • 7.1 std::promise
      • 7.2 std::future
      • 7.3 std::packaged_task
    • 八、async
    • 九、call_once

一、std::thread

C++11中提供std::thread创建线程执行线程任务,不再需要使用繁琐的pthread_xxx;

1.1 成员函数

  • 构造函数
// 1 提供默认构造;
thread() noexcept;

// 2 提供初始化构造函数,即创建线程任务
// Fn 执行函数
// Args 执行函数的参数列表
template <class Fn, class... Args>explicit thread (Fn&& fn, Args&&... args);

// 禁止拷贝构造
thread (const thread&) = delete;

// 3 提供移动构造函数
thread (thread&& x) noexcept;
  • get_id
// 获取当前线程的ID
id get_id() const noexcept;

// 获取当前线程ID
std::this_thread::get_id()
  • joinable
// 检查当前线程是否可接合
bool joinable() const noexcept;
// 【以下情况不可接合】:
// - 是默认构造
// - 从(构造另一个线程对象,或赋值给它)移动
// - 任何一个成员加入或脱离被调用
  • join
// 主线程会等待该线程执行完成,当该线程执行完成后返回,当前线程对象jsonable为false
void join();
  • detach
// 线程分离
// 将当前线程和主线程分离,允许独立执行;两个线程运行,不会阻塞,当线程执行玩,即被销毁
void detach();
  • native_handle
// 获取操作系统原生的线程句柄pthread_xxx
// 若存在,则返回
native_handle_type native_handle();
  • hardware_concurrency
// 获取当前CPU的个数
static unsigned hardware_concurrency() noexcept;

1.2 案例

#include <thread>
#include <iostream>
#include <unitsd.h>

void func1() {
	std::cout << "func1" << std::endl;
	std::cout << "func1 当前线程ID: " << std::this_thread::get_id() << std::endl;
	std::cout << "func1 end" << std::endl; 
}

void func2(int n) {
	std::cout << "func2" << std::endl;
	std::cout << "args: " << n << std::endl; 
	sleep(2);
	std::cout << "fucn2 当前线程ID: " << std::this_thread::get_id() << std::endl;
	std::cout << "func2 end" << std::endl;
}

int main() {
	std::thread t1(func1);
	std::thread t2(func2, 19);
	t1.join();
	t2.detach();
	sleep(5);
	return 0;
}
/// t1执行完会返回,t2为分离线程执行完毕后即销毁

二、std::mutex

用于保存多线程同时操作的共享数据;主要有四种类型:

  • std::mutex:独占的互斥量;
  • std::recursive_mutex:递归互斥量,可重入;
  • std::timed_mutex:带超时的互斥量;
  • std::recursive_timed_mutex:带超时的互斥量,可以递归使用;

========》递归锁的讨论《========

在这里插入图片描述

三、std::lock

可以动态的释放锁资源,防止线程由于编码失误导致一直持有锁;

  • std::lock_guard;
  • std::unique_lock;

在这里插入图片描述

当进入到lock的当前作用域时自动上锁,离开当前作用域时自动释放锁;

3.1 lock_guard

// 该类只提供默认构造以及一个有参构造
// 拷贝构造和赋值操作符被delete
// 数据成员只有一个

在这里插入图片描述

3.2 unique_lock

/// 该类提供多种构造方式,可自设定是否需要完成持有该mutex,是否要设置超时;
/// 对于复制拷贝及赋值操作符都delete,但提供移动拷贝构造和赋值;
/// 额外提供lock、unlock、try_lock等;

在这里插入图片描述

3.3 lock_guard与unique_lock的对比

  • unique_lock会更加灵活,但占用空间更大,速度会更慢一些,需要维护mutex的状态;
  • unique_lock提供默认构造,不一定拥有mutex,unique_lock同样不可复制,但具有move语义,故可用于函数或STL的容器中;
  • unique_lock额外提供lock,unlock,try_locl等

四、std::atomic

原子操作:多线程中最小的不可并行化的操作,故在多线程下,只有一个线程对其进行操作(不会出现例外);

  • 通过互斥的访问来保证;
  • 不需要通过加锁去锁的繁杂操作;

用法:

  • atomic t ==> 可以通过T来指定任意类型;
  • 原子类型只能从其模板参数类型中构造,不允许原子类型进行拷贝、移动构造;
  • 可以隐式转换T类型;

【atomic_flag】:该类型为无锁的,可以用该类型来实现一个自旋锁;

在这里插入图片描述

五、volatile

参考文章【C++模块实现】| 【07】对于互斥、自旋锁、条件变量、信号量简介及封装 1.6

六、condition_variable

可参考之前使用pthread_xxx版本的:Linux【线程】 | 【01】线程、线程同步、线程安全

它可以阻塞一个线程或者个线程,直到有线程通知或者超时才会唤醒正在阻塞的线程,条件变量需要和锁配合使用;

在这里插入图片描述

成员函数

// 默认构造
condition_variable();

// 拷贝构造被禁止
condition_variable (const condition_variable&) = delete;

// 等待变量条件通知,传入unique_lock
void wait (unique_lock<mutex>& lck);	
template <class Predicate>  
void wait (unique_lock<mutex>& lck, Predicate pred);

// 等待超时或直到通知,传入unique_lock
// 可通过wait_for的返回值是否为std::cv_status::timeout来判断当前通知是否超时
template <class Rep, class Period>  
cv_status wait_for (unique_lock<mutex>& lck,const chrono::duration<Rep,Period>& rel_time);

// wait_until和wait_for类似,只不过时间段被替换成了时间点
template <class Clock, class Duration>  
cv_status wait_until (unique_lock<mutex>& lck, const chrono::time_point<Clock,Duration>& abs_time);

// 唤醒某个等待线程,如果没有线程在等待,那么这个函数什么也不做,如果有多个线程等待,唤醒哪个线程是随机的
void notify_one() noexcept;

// 唤醒所有的等待线程
void notify_all() noexcept;

// 枚举,判断状态
std::cv_status{
	no_timeout,
	timeout
}

七、future、promise、packaged_task

c++11关于异步操作提供了future相关的类,主要有std::futurestd::promisestd::packaged_task;

  • std::future:异步结果的传输通道,通过get()可获取线程函数的返回值,std::future是不可以复制的,若要复制放到容器中可以使用std::shared_future。
  • std::promise:用来包装一个值,将数据和future绑定起来;
  • std::packaged_task:用来包装一个调用对象,将函数和future绑定起来,方便异步调用;

7.1 std::promise

  • 该类可存储T类型的值,提供给future对象;
  • 该类通过get_future关联到futrue对象上,调用后,两个对象共享相同的共享状态;
  • futrue是异步返回对象,它的get方法会阻塞等待promise设定val;
// 提供默认构造
promise();
// 提供带参数,可自定义分配器
template <class Alloc> promise (allocator_arg_t aa, const Alloc& alloc);
// 禁用拷贝构造
promise(const promise&) = delete;
// 提供移动拷贝构造
promise(promise&& x) noexcept;

// 获取与共享状态相关联的future对象
future<T> get_future();

// 将val存储为共享状态的值,共享状态变为ready
void set_value (const T& val);void set_value (T&& val);

// 将异常指针p存储在共享状态,该状态变为ready
// 解除future::get的阻塞并抛出由p指向的异常对象
void set_exception (exception_ptr p);

7.2 std::future

  • 是一个可从某个提供者对象或函数检索值的对象;
  • 再某个线程上调用futrue::get将会阻塞该线程,知道提供者提供好共享状态和值,以此来实现两个线程设置值的同步;
// 提供默认构造
future() noexcept;
// 禁止拷贝构造
future (const future&) = delete;
// 提供移动构造
future (future&& x) noexcept;

// 返回一个shared_future对象,用于获取未来对象的共享状态
shared_future<T> share();

// 当共享状态就绪时,返回存储在共享状态中的值;若未就绪,则等待
T get();
R& future<R&>::get();      
void future<void>::get();   

// 检查future对象当前是否与共享状态相关联
bool valid() const noexcept;

// 阻塞等待共享状态准备就绪
void wait() const;
template <class Rep, class Period>  future_status wait_for (const chrono::duration<Rep,Period>& rel_time) const;
template <class Clock, class Duration>  future_status wait_until (const chrono::time_point<Clock,Duration>& abs_time) const;

7.3 std::packaged_task

  • 包装了一个可调用元素,允许异步检索其结果;
  • 类似std::function,但该类是将其结果自动传递给future对象;
// 提供默认构造
packaged_task() noexcept;
// 提供带参构造,为函数签名
template <class Fn>  explicit packaged_task (Fn&& fn);
// 提供带参构造,为分配器及函数签名
template <class Fn, class Alloc>  explicit packaged_task (allocator_arg_t aa, const Alloc& alloc, Fn&& fn);
// 禁止拷贝构造
packaged_task (packaged_task&) = delete;
// 提供移动构造
packaged_task (packaged_task&& x) noexcept;

// 检查有效的共享状态
bool valid() const noexcept;

// 返回与对象的共享状态相关联的future对象
future<Ret> get_future();

// 调用存储的任务,转发参数作为它的参数
void operator()(Args... args);

// 使用新的共享状态重置对象,同时保持相同的存储任务
void reset();

八、async

  • 返回的对象是一个future对象,保存函数的执行结果;
  • 使用该类,即直接传入一个函数名称, 后续跟上参数即可;
  • 策略标志,枚举类型:
    • std::launch::async:调用async即开始创建线程;
    • std::launch::deferred:没有创建线程,在主线程中调用入口函数;为延时调用,当调用future的wait和get,才执行入口函数;
      在这里插入图片描述

在这里插入图片描述

九、call_once

  • 来保证某一函数在多线程环境中只调用一次,它需要配合std::once_flag使用;
std::once_flag onceflag;

void CallOnce() {
   std::call_once(onceflag, []() {
       cout << "call once" << endl;
  });
}

int main() {
   std::thread threads[5];
   for (int i = 0; i < 5; ++i) {
       threads[i] = std::thread(CallOnce);
  }
   for (auto& th : threads) {
       th.join();
  }
   return 0;
}

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

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

相关文章

【Cloudcone】VPS 登录、防火墙设置

服务器登录、防火墙设置本来是一件很简单的事情&#xff0c;但是我买了国外服务器&#xff0c;有些地方出现了一些问题。 文章目录一、简介二、使用ipv6登录服务器三、防火墙设置四、小插曲一、简介 我一直用的腾讯云的服务器&#xff0c;但是带宽太低了&#xff0c;只有4M。最…

2023年二月份图形化三级打卡试题

活动时间 从2023年 2月1日至1月21日&#xff0c;每天一道编程题。 本次打卡的规则如下&#xff1a; &#xff08;1&#xff09;小朋友每天利用10~15分钟做一道编程题&#xff0c;遇到问题就来群内讨论&#xff0c;我来给大家答疑。 &#xff08;2&#xff09;小朋友做完题目后&…

CSS第四章——文本属性

文章目录4.1 文本颜色4.2 对齐文本4.3 装饰文本4.4 文本缩进4.5 行间距一些学习笔记。 CSS Text&#xff08;文本&#xff09;属性可定义文本的外观&#xff0c;比如文本的颜色、对齐文本、装饰文本、文本缩进、行间距等。 属性表示注意点color文本颜色通常使用十六进制 而且…

【算法题解】13. 删除链表的倒数第 N 个结点

文章目录题目解法一&#xff1a;计算链表长度Java 代码实现Go 代码实现复杂度分析解法二&#xff1a;双指针Java 代码实现Go 代码实现复杂度分析这是一道 中等难度 的题。 题目来自&#xff1a;https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/ 题…

numpy快速交换行列

import numpy as np “”" 快速加换两行两列 “”" #交换两列第一列跟第三列 v1np.arange(100) v2v1.reshape((20,5)) v3v2[:,[0,3,2,1,4]] print(v3) “”" 快速交换两列 第一列跟第三列 “”" print() mask list(range(5))#生成一个0到4的列表 #快速…

[iHooya]2023年1月30日作业解析

温度统计 现有一段时间的温度数据&#xff0c;请统计指定温度出现的次数。 输入 第一行一个整数n,表示温度数据的个数。&#xff08;0 < n ≤ 200&#xff09; 第二行n个整数&#xff0c;以空格分隔&#xff0c;每个整数表示一个温度&#xff0c;温度的范围大于等于0&#…

OpenCV实战(9)——基于反向投影直方图检测图像内容

OpenCV实战&#xff08;9&#xff09;——基于反向投影直方图检测图像内容0. 前言1 反向投影直方图2. 反向投影颜色直方图3. 完整代码小结系列链接0. 前言 直方图是图像内容的一个重要特征。如果查看显示特定纹理或特定对象的图像区域&#xff0c;则该区域的直方图可以看作是一…

计算机网络之TCP全连接队列与半连接队列

什么是全、半连接队列 服务端接收syn请求后&#xff0c;内核会把该连接放入到半连接队列&#xff0c;服务端对synack返回ack后&#xff0c;会把连接从半连接队列移除&#xff0c;创建新的全连接&#xff0c;并把新的连接放入全连接队列 查看全连接队列的命令 全连接队列满了…

Deep Learning Tuning Playbook(深度学习调参手册中译版)

前言 由五名研究人员和工程师组成的团队发布了《Deep Learning Tuning Playbook》&#xff0c;来自他们自己训练神经网络的实验结果以及工程师的一些实践建议&#xff0c;目前在Github上已有1.5k星。原项目地址本文为《Deep Learning Tuning Playbook》中文翻译版本&#xff0…

聊一聊微信小程序生命周期你最想知道的一些事

目录 前言 解析 运行机制 总结 前言 &#xff08;1&#xff09;为什么是微信小程序 最近有人问我一些关于微信小程序的问题&#xff0c;今天有时间也就整理了一些微信小程序的相关资料&#xff0c;给大家简单系统总结一些微信小程序的相关知识及生命周期。 &#xff08;2…

使用光泵磁力仪(OPMs)非接触测量视网膜活动

使用光泵磁力仪&#xff08;OPMs&#xff09;非接触测量视网膜活动摘要绪论方法2.1参与者和测量设置2.2刺激2.3数据分析结果讨论原文见&#xff1a; https://www.sciencedirect.com/science/article/pii/S1053811921008016 摘要 光泵磁力仪&#xff08;OPM&#xff09;已被用…

关于提升销量和排名,亚马逊、wish、ebay卖家该怎么做?

新年好&#xff0c;我是龙哥测评&#xff0c;在这里祝愿所有跨境朋友在新的一年里财源滚滚&#xff0c;一切顺利。 接下来龙哥就来说说&#xff0c;为什么店铺销量提升不上去&#xff0c;产品曝光低转化率低&#xff0c;产品有排名但是没销量&#xff0c;等等这些问题&#xf…

5 个我们仍可 Solana 在熊市危机报有希望的原因

Daniel, 2022 年 1 月前面&#xff0c;我们发表了 《9 大指标分析 Solana 的熊市危机》。当查看数据时&#xff0c;有一个很好的论据&#xff0c;即 Solana 在 2021/2022 年期间严重超卖&#xff0c;该网络没有项目、TVL 或用户来维持自己度过长期的熊市。它的崩溃只是更严重&a…

QT/C++——主窗口和事件处理

一、主窗口 上面就是一个主窗口&#xff0c;主窗口中的每一个都是Action 这次新建工程要选择mainwindow #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QAction> #include <QTextEdit> #include <QLabel> #include &l…

LeetCode 剑指 Offer 09. 用两个栈实现队列

题目 解题 这道题是用两个栈实现一个队列&#xff0c;具有一个队尾添加元素和队头删除元素的功能 这里思路是一个进&#xff0c;一个出&#xff0c;里面的元素顺序很关键&#xff0c;要保持一个进栈最先进的元素在另一个出栈的栈顶 第一种方法是&#xff0c;每次进元素&#x…

冰冰学习笔记:信号

欢迎各位大佬光临本文章&#xff01;&#xff01;&#xff01; 还请各位大佬提出宝贵的意见&#xff0c;如发现文章错误请联系冰冰&#xff0c;冰冰一定会虚心接受&#xff0c;及时改正。 本系列文章为冰冰学习编程的学习笔记&#xff0c;如果对您也有帮助&#xff0c;还请各位…

使用Postman快速访问MemFire Cloud应用

“超能力”数据库&#xff5e;拿来即用&#xff0c;应用开发人员再也不用为撰写API而发愁。MemFire Cloud 为开发者提供了简单易用的云数据库&#xff08;表编辑器、自动生成API、SQL编辑器、备份恢复、托管运维&#xff09;&#xff0c;很大地降低开发者的使用门槛。 使用Post…

关于保研(免试攻读硕士学位研究生)的相关政策

文章目录1、保研政策是什么&#xff1f;2、哪些学校可以保研&#xff1f;3、保研的流程/名额是怎样的&#xff1f;1、保研政策是什么&#xff1f; 什么是保研&#xff1f; 官方定义&#xff1a; 保研&#xff08;全称&#xff1a;推荐优秀应届本科毕业生免试攻读硕士学位研究…

Linux基础开发环境,yum 与 vim。

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 &#x1f4ac;<4>前言&#xff1a;Linux必不可少的基础开发环境使用。 目录 一.Linux软件包管理器 yum &#x…

微电网经济优化运行(光伏、储能、柴油机)(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…