【C++并发与多线程】 10_shared_future、automic

逻辑追月客
• 阅读 2009

std::shared_future

类模板

template <class T>  shared_future;
template <class R&> shared_future<R&>;   // specialization : T is a reference type (R&)
template <>         shared_future<void>; // specialization : T is void
  • 一个 shared_future 对象行为类似于 future 对象,除了它可以被赋值,而且一个以上的 shared_future 可以在他们的共享状态结束时共享所有权。它们还被允许一旦准备好就多次检索共享状态下的值。
  • shared_future 对象可以从 future 对象隐式转换,也可以通过 future::share 显式获得。在这两种情况下,原 future 对象自身将失效。
  • 共享状态的生存期至少要持续到与之关联的最后一个对象被销毁为止。从 shared_future 中获取值(使用成员函数 get) 不会释放其对共享状态的所有权(与 future 不同)。因此,如果与 shared_future 对象相关联,则共享状态可以在最初获得它的对象(如果有的话)之后继续存在。
成员函数描述
get当共享状态就绪时,返回存储在共享状态中的值的引用(或引发其异常)
valid检查 shared_future 对象是否与共享状态关联
wait等待共享状态准备就绪
wait_for等待共享状态在 rel_time 指定的时间内准备就绪
wait_until等待共享状态准备就绪,最多直到abs_time时间点
#include <iostream>
#include <thread>
#include <future>

using namespace::std;

int mythread()
{
    cout << "mythread begin" << endl;

    this_thread::sleep_for(chrono::microseconds(5000));

    cout << "mythread end" << endl;

    return 5;
}

int main()
{
    cout << "main begin" << endl;

    future<int> result = async(launch::async, mythread);
    shared_future<int> result_s = result.share();

    // 等价
    // shared_future<int> result_s = async(launch::async, mythread);

    if (result_s.valid())
    {
        cout << result_s.get() << endl;

        cout << result_s.get() << endl;

        cout << result_s.get() << endl;
    }

    cout << "main end" << endl;

    return 0;
}

输出:

main begin
mythread begin
mythread end
5
5
5
main end

std::atomic 原子操作

类模板

template <class T> struct atomic;
  • 原子操作是指不会被线程调度机制打断的操作。这种操作一旦开始,就一直运行到结束,中间不会有任何任何上下文切换。
  • 原子操作可以是一个步骤,也可以是多个操作步骤,但其顺序不可被打乱,也不可以被切合只执行其中一部分。
  • 将整个操作视作一个整体是原子操作的核心特征。

编程实验

  • 非原子操作,不加锁,效率很高,但无法得到正确的结果
  • 非原子操作,加锁,效率很低,但结果正确
  • 原子操作,效率很高,且结果正确

测试1:非原子操作,无锁

#include <iostream>
#include <thread>

using namespace::std;

int g_sum = 0;

void add()
{
    for (uint32_t i=0; i<10000000; ++i)
        ++g_sum;
}

int main()
{
   auto beginTime = clock();

   thread t1(add);
   thread t2(add);

   t1.join();
   t2.join();

   auto endTime = clock();

   cout << "time consuming  : " << endTime - beginTime << endl;
   cout << "calculated value: " <<  g_sum << endl;

    return 0;
}

输出:[速度快,结果错误]

time consuming  : 47
calculated value: 10856025

测试2:非原子操作,有锁

#include <iostream>
#include <thread>
#include <mutex>

using namespace::std;

int g_sum = 0;
mutex g_mutex;

void add()
{
    for (uint32_t i=0; i<10000000; ++i)
    {
        g_mutex.lock();
        ++g_sum;
        g_mutex.unlock();
    }
}

int main()
{
   auto beginTime = clock();

   thread t1(add);
   thread t2(add);

   t1.join();
   t2.join();

   auto endTime = clock();

   cout << "time consuming  : " << endTime - beginTime << endl;
   cout << "calculated value: " <<  g_sum << endl;

    return 0;
}

输出:[结果正确,速度慢]

time consuming  : 571
calculated value: 20000000

测试3:原子操作

#include <iostream>
#include <thread>
#include <atomic>

using namespace::std;

atomic<int> g_sum {0};

void add()
{
    for (uint32_t i=0; i<10000000; ++i)
    {
        ++g_sum;
    }
}

int main()
{
   auto beginTime = clock();

   thread t1(add);
   thread t2(add);

   t1.join();
   t2.join();

   auto endTime = clock();

   cout << "time consuming  : " << endTime - beginTime << endl;
   cout << "calculated value: " <<  g_sum << endl;

    return 0;
}

输出:[速度快,结果正确]

time consuming  : 292
calculated value: 20000000

一般用法

  • 用于多线程环境中的访问标记
  • 用于多线程环境中的访问统计
#include <iostream>
#include <thread>
#include <atomic>

using namespace::std;

atomic<bool> g_ifEnd {false};

void mythread()
{
    cout << "mythread begin" << endl;

    chrono::microseconds dura(1000);

    while (!g_ifEnd)
    {
        cout << "mythread thread id :" << this_thread::get_id() << endl;

        this_thread::sleep_for(dura);
    }

    cout << "mythread begin" << endl;
}

int main()
{
   cout << "main end" << endl;

   thread t1(mythread);

   this_thread::sleep_for(chrono::microseconds(5000));

   g_ifEnd = true;

   t1.join();

   cout << "main end" << endl;

    return 0;
}

输出:

main end
mythread begin
mythread thread id :2
mythread begin
main end
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这