目录

一、std::future的其他成员函数

二、std::shared_future

三、原子操作std::atmic


在上篇:C++11多线程---async、future、package_task、promise_阿巴乾的博客-CSDN博客

已经介绍了future的一些成员函数,比如get。在这篇继续介绍future的一些其他成员函数,以及shared_future、atomic。

一、std::future的其他成员函数

//
// Created by yangjq on 22-7-8.
//
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
#include <future>using namespace std;int mythread() {cout << "mythread started !" << " thread_id = " << std::this_thread::get_id() << endl;std::chrono::milliseconds dura(5000);std::this_thread::sleep_for(dura);cout<<"mythread end !" << " thread_id = " << std::this_thread::get_id() << endl;return 5;
}int main() {cout << "main" << " thread_id = " << std::this_thread::get_id() << endl;std::future<int> result = std::async(std::launch::deferred,mythread);cout << "continue ..... " << endl;//枚举类型std::future_status status = result.wait_for(std::chrono::seconds(6));//等待1秒if(status == std::future_status::timeout){//线程超时,等待了一秒,但是线程要五秒cout << "超时了,线程没执行完" << endl;}else if(status == std::future_status::ready){cout << "线程成功执行完了" << endl;cout << result.get() << endl;}else if(status == std::future_status::deferred){//延迟//如果async的第一参数被设置为std::launch::deferred,则本条件成立cout << "线程被延迟执行" << endl;cout << result.get() << endl;}cout << "main end !" << endl;return 0;
}

二、std::shared_future

在上篇讲到了get,但是对于结果result只能get一次,再次get会出错,这是因为get函数的设计是一个移动语义。如果对于多个地方需要得到返回值的话,get就不够用了,这时候就需要std::shared_future。

//
// Created by yangjq on 22-7-8.
//
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
#include <future>using namespace std;int mythread(int mypar) {cout << "mythread" << " thread_id = " << std::this_thread::get_id() << endl;std::chrono::milliseconds dura(5000);std::this_thread::sleep_for(dura);return 5;
}void mythread2(std::shared_future<int> &tmpf){cout << "mythread2" << " thread_id = " << std::this_thread::get_id() << endl;auto result = tmpf.get();cout << "mythread2 result = " << result <<endl;return;
}int main() {cout << "main" << " thread_id = " << std::this_thread::get_id() << endl;std::packaged_task<int(int)> mypt(mythread);//把函数mythread通过packaged_task包装起来std::thread t1(std::ref(mypt), 1);cout << "continue ..... " << endl;t1.join();std::shared_future<int> result_s(mypt.get_future());//result会变成空,值会到result_s里面去std::thread t2(mythread2, std::ref(result_s));t2.join();cout << "main end !" << endl;return 0;
}

三、原子操作std::atmic

互斥量:多线程编程中,保护共享数据。

问题:有两个线程,只对一个变量进行操作,一个进行读操作,一个进行写操作。程序结果会出现问题,这个问题主要在于线程与线程之间对一个变量的操作会导致冲突,语句无法正常执行。比如一个赋值语句可以拆分成三四句汇编语句,当另一个线程来对变量进行操作时,可能这个线程还未将赋值进行完毕。

以下面这段代码为例:

//
// Created by yangjq on 22-7-11.
//
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
#include <future>using namespace std;int g_mycont = 0;void mythread(){for(int i = 0; i < 1000000; i++){g_mycont++;}return;
}int main(){thread mytobj1(mythread);thread mytobj2(mythread);mytobj1.join();mytobj2.join();cout << "两个线程执行完毕!g_mycont = " << g_mycont << endl;
}

这段代码从编写思路上来讲,应该是期待全局变量g_mycont输出为2000000,但是实际输出确每次都不到2000000,并且每次都不一样。因此,代码是不稳定的。如果想让代码稳定,想法当然是进行加锁。如下代码:

    for(int i = 0; i < 1000000; i++){g_my_mutex.lock();g_mycont++;g_my_mutex.unlock();}

在循环进行加锁解锁,但是这种加锁解锁也会浪费很多时间,因此就出现了原子操作这种更好的方式来解决这个问题。原子操作可以理解为一种不需要用到互斥量加锁技术的多线程并发编程方式。原子操作是在多线程中不会被打断的程序执行片段,在效率上比互斥量更胜一筹。互斥量的加锁一般是针对一个代码段,而原子操作针对的一般都是一个变量,而不是一个代码段。

//
// Created by yangjq on 22-7-11.
//
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include <mutex>
#include <future>using namespace std;
std::atomic<int> g_mycont;void mythread(){for(int i = 0; i < 1000000; i++){g_mycont++;}return;
}int main(){g_mycont = 0;thread mytobj1(mythread);thread mytobj2(mythread);mytobj1.join();mytobj2.join();cout << "两个线程执行完毕!g_mycont = " << g_mycont << endl;
}

以上代码是原子操作的用法范例。

在这个范例中使用++操作符,输出是没有任何问题的。但是像下面代码简单修改一下就会出错。

void mythread(){for(int i = 0; i < 1000000; i++){g_mycont = g_mycont + 1;}return;
}

按以上代码修改后运行结果不是2000000,主要原因还是atomic不支持这样的操作,一般atomic支持的操作有++,--,+=,-=,&=,|=,^=,其他的可能不支持。

总结:原子操作可以理解为在现实世界中,把原子理解为最小的物质组成单位(虽然还有更小的电子等等);在代码中,把一个赋值或其他语句作为不可分割的语句,只有两种状态,要么赋值完成,要么赋值失败。这样就不会出现多线程时,读写冲突的问题,并且效率会比使用互斥量更高。

参考:c++11并发与多线程视频课程_哔哩哔哩_bilibili

C++11多线程---future、shared_future、atomic相关推荐

  1. [C++] - C++11 多线程 - Future

    整理转自:https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/tree/master/zh/chapter6-Future Ta ...

  2. C++11多线程のfuture,promise,package_task

    一.c++11中可以在调用进程中获取被调进程中的结果,具体用法如下 // threadTest.cpp: 定义控制台应用程序的入口点. // #include "stdafx.h" ...

  3. C++11多线程---future和promise

    future和promise的作用是在不同线程之间传递数据.使用指针也可以完成数据的传递,但是指针非常危险,因为互斥量不能阻止指针的访问:而且指针的方式传递的数据是固定的,如果更改数据类型,那么还需要 ...

  4. C++11 并发指南一(C++11 多线程初探)

    引言 C++11 自2011年发布以来已经快两年了,之前一直没怎么关注,直到最近几个月才看了一些 C++11 的新特性,今后几篇博客我都会写一些关于 C++11 的特性,算是记录一下自己学到的东西吧, ...

  5. 与 C++11 多线程相关的头文件

    C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是<atomic> ,<thread>,<mutex>,<condition_variable& ...

  6. [C++] - C++11 多线程 - Thread

    转载整理自:https://github.com/forhappy/Cplusplus-Concurrency-In-Practice/tree/master/zh/chapter3-Thread 1 ...

  7. C++11 多线程库使用说明

    多线程基础 1.1 进程与线程 根本区别: 进程是操作系统资源分配的基本单位,线程是任务调度和执行的基本单位 开销方面: 每个进程都有自己独立的代码和数据空间,程序之间的切换开销较大. 线程可以看作是 ...

  8. C++11 多线程(std::thread)详解

    注:此教程以 Visual Studio 2019 Version 16.10.3 (MSVC 19.29.30038.1) 为标准,大多数内容参照cplusplus.com里的解释 此文章允许转载, ...

  9. C++11中头文件atomic的使用

    原子库为细粒度的原子操作提供组件,允许无锁并发编程.涉及同一对象的每个原子操作,相对于任何其他原子操作是不可分的.原子对象不具有数据竞争(data race).原子类型对象的主要特点就是从不同线程访问 ...

最新文章

  1. 从零开始入门 K8s| 阿里技术专家详解 K8s 核心概念
  2. 首届中国服务创新大会在深举办 助力产业智慧升级
  3. android init.d脚本,◇添加init.d脚本支持教程贴◇
  4. 发布!天池布匹疵点检测大赛解决方案与Baseline(acc:85%左右,mAP:52%左右)
  5. WSGI、flup、fastcgi、web.py的关系
  6. 全网首发:gpg: gpg-agent 在此次会话中无法使用的解决办法
  7. 已知s=1×2×3×…×n,计算出s不大于5000时n的最大值。
  8. Pandorabox等类OpenWrt的路由器 实现后端设备接入IPV6(中继代理+NAT)
  9. 凸优化第七章统计估计 7.1参数分布估计
  10. 关于计算机网络安全实验报告总结,信息安全实验总结报告
  11. Java学习之多线程
  12. 常见水果/蔬菜/植物nbsp;英语词汇大全
  13. Android 字体引入
  14. wamp5如何配置多个自定义域名访问本地不同的项目
  15. 虚幻4渲染编程(环境模拟篇)【第一卷:体积云天空模拟(1)---层云】
  16. 多维数组扁平化的方法
  17. 单片机原理及应用 实验四 指示灯数码管的中断控制
  18. 21. 理解CNI和CNI插件
  19. 关于gbk乱码问题(前程无忧)
  20. 发一段开启摄像头的代码

热门文章

  1. C#生成PDF页脚第几页共几页
  2. GDI 开发的准备工作
  3. nodejs+vue+elementui游戏新闻资讯网站管理系统
  4. 薄型轴承产品特性及其优势
  5. python前后端分离项目部署_nginx+uwsgi+supervisor部署django前后端分离项目
  6. 决策树基础—比特化Bits,信息熵,条件熵,联合熵
  7. Python能成为通用编程开发语言的10大原因
  8. 文献推荐:植物细胞全能性和再生
  9. 跨域问题JAVA后台设置cors跨域中关于access-control-allow-headers导致的错误
  10. 【easyui】解决easyui闪屏问题