文档章节

Multi thread: std::shared_future(2)

SHIHUAMarryMe
 SHIHUAMarryMe
发布于 2016/05/13 15:44
字数 776
阅读 101
收藏 0
点赞 2
评论 0

在之前我们了解到std::future,但是通过class std::future获得的结果只能get()一次,第二次调用通常会抛出一个std::future_error。

但是当多个其他线程想处理另外一个线程的结果的时候,也就是需要多次get(),基于这个目的C++ standard library提供了 std::shared_future,于是我们就可以多次调用get(),拿到相同的结果,或者抛出(throw)同一个异常.

std::shared_future相对于std::future来说只是少了一个share()操作.别的操作基本上是与 std::future一致的.此外还有以下几点不同:

1, std::future是不能被拷贝的(但是需要注意的是std::fututre和std::shared_future一样都是支持move的).

2, std::shared_future可以多次调用get().

3, std::future可以通过std::future::shared()获得一个std::shared_future(当然这会导致std::future无效).

 

 

我们来看一个例子吧:

#include <iostream>
#include <future>
#include <thread>
#include <exception>
#include <stdexcept>

int queryNumber()
{
	std::cout << "enter a number: ";
	int number;
	std::cin >> number;

	if (!std::cin) {
		throw std::runtime_error(std::string("no number read!"));
	}

	return number;
}

void doSomething(const char& c, const std::shared_future<int>& f)
{
	try {
		int number = f.get();

		for (int i = 0; i < number; ++i) {
			std::this_thread::sleep_for(std::chrono::duration<int, std::ratio<1, 1000>>(1));
			std::cout.put(c).flush();
		}

	}catch (const std::exception& e) {
		std::cerr << "EXCEPTION in thread" << std::this_thread::get_id() << ": " << e.what() << std::endl;
	}
}

int main()
{
	try {
		std::shared_future<int> result = std::async(std::launch::async, queryNumber);
		
		std::future<void> result1 = std::async(std::launch::async, doSomething, '.', result); 
		//注意我们在std::async()中传递的参数result其实是对result的拷贝.
		//如果我们写成std::async(std::launch::async, '.', std::ref(result));这种情况下才是对result的引用.
		//这样一来就是对一个std::shared_future多次调用get()了.于是就带来了风险.
		std::future<void> result2 = std::async(std::launch::async, doSomething, '+', result);
		std::future<void> result3 = std::async(std::launch::async, doSomething, '*', result);

		result1.get();
		result2.get();
		result3.get();

	}catch (const std::exception& e) {
		std::cout << "\nEXCEPTION: " << e.what() << std::endl;
	}

	std::cout << "\ndone" << std::endl;

	return 0;
}

std::async与传递实参到callable object

首先来看一个例子:

#include <iostream>
#include <thread>
#include <chrono>
#include <future>
#include <random>

void doSomething(const char& c)
{
	std::default_random_engine engine(c);
	std::uniform_int_distribution<int> distribution(10, 100);

	for (int i = 0; i < 10; ++i) {
		std::this_thread::sleep_for(std::chrono::milliseconds(distribution(engine)));
		std::cout.put(c).flush();
	}
}

int main()
{
	std::cout << "starting 2 operation asynchronously" << std::endl;
	std::future<void> result1(std::async([]() { doSomething('.'); }));
	std::future<void> result2(std::async([]() { doSomething('+'); }));

	//下面首先检查是否被推迟调用了.
	if (result1.wait_for(std::chrono::seconds(0)) != std::future_status::deferred || result2.wait_for(std::chrono::seconds(0)) != std::future_status::deferred) {

        //循环检测std::future中的shared state是否被设置好了.
		while (result1.wait_for(std::chrono::seconds(0)) != std::future_status::ready && result2.wait_for(std::chrono::seconds(0)) != std::future_status::ready) {
			std::this_thread::yield();
		}
	}

	std::cout.put('\n').flush();

	try {
		result1.get();
		result2.get();

	}catch (const std::exception& e) {
		std::cout << "\nEXCEPTION: " << e.what() << std::endl;
	}

	std::cout << "\ndone" << std::endl;

}

在上面的例子中我们都是by-value(拷贝)的形式传值进去callable object.

如果是by-reference:

char c = '@';
std::future<void> result3 = std::async([&](){ doSomething(c); });

//或者是:
std::future<void> result4 = std::async(doSomething, std::ref(c));
//注意上面的std::ref;

这样一来就产生了data-race(数据竞争),而且如果其中的一个线程修改了c的值,另外一个线程可能出来的结果就不是我们先要的了.因此最好还是by-value的形式传值进去.

© 著作权归作者所有

共有 人打赏支持
SHIHUAMarryMe
粉丝 12
博文 165
码字总数 138772
作品 0
武汉
程序员
Multi thread: std::promise

前面我们了解到可以使用std::sharedfuture/std::sharedfuture在多个其他线程中处理另外一个线程的函数的返回结果. 那么疑问来了,我们要怎样在多线程之间传递数据呢? demo1 :std::promise在线...

SHIHUAMarryMe ⋅ 2016/05/14 ⋅ 0

Multi thread: std::async()和std::future(1)

对于初学者而言,“以多线程运行程序”的最佳起点就是C++标准库中的 std::async() 和 class std::future提供的高级接口. (1),std::async()提供一个接口,让一段机能或者说一个callable obje...

SHIHUAMarryMe ⋅ 2016/05/10 ⋅ 0

C++11: std::packaged_task

class std::packaged_task被用来同时存储callable object,以及该callable object的返回值(也可能是个异常). ----------------------------我是分割线------------------------------ std:......

SHIHUAMarryMe ⋅ 2016/05/15 ⋅ 0

C++11实现跨平台线程池

生产者消费者 转自:http://www.cnblogs.com/sanjin/archive/2012/08/09/2629890.html std::conditionvariable的使用方法如下: ·当持有锁(mutex)之后,线程调用wait ·wait解开持有的互斥锁...

初雪之音 ⋅ 2016/03/19 ⋅ 0

shared_ptr 的使用及注意事项

1. 声明 #include class UsersBitmap { ... } typedef boost::shared_ptr UsersBitmapPtr; 2. 使用 UsersBitmapPtr loginusers; UsersBitmapPtr temploginusers(new UsersBitmap()); //指向对......

xumaojun ⋅ 03/07 ⋅ 0

boost asio 多线程异步服务器历程

场景说明 本例子支持多线程异步处理消息,针对每一个链接请求,创建线程处理稍后的指令,CSimpleSession::SessionThreadFunc是线程函数,asyncreadsome函数设置接收数据的回调函数ContinueRea...

技术小胖子 ⋅ 2017/11/08 ⋅ 0

C++11简摘

C++11特性: 1、右值引用,move 2、泛化的常数表示,constexpr 3、外部模板,extern 4、初始化列表,std::initializer_list<> 5、统一的初始化,{} 6、类型推导,auto,decltype 7、范围for...

悠米海 ⋅ 2016/08/27 ⋅ 0

Mutex mutandis: understanding mutex types and attr

The mutex is a simple little thing with one job to do: ensure mutual exclusion between threads. Yet Linux has up to 16 variations of the mutex, depending on which versions of th......

LsDimplex ⋅ 2016/07/19 ⋅ 0

java 多线程,及获取线程执行结果

Thread、Runnable 创建多线程 *** FutureTask 获取线程执行结果 *** ExecutorService 更简便的获取线程执行结果方式 *** ThreadPoolExecutor 线程池 多线程缺点:频繁创建、销毁线程 线程池:...

jack_0110 ⋅ 2016/12/27 ⋅ 0

Thrift辅助类,用于简化Thrift编程

CThriftServerHelper用于服务端,CThriftClientHelper用于客户端。 源代码链接:https://github.com/eyjian/mooon/blob/master/mooon/include/mooon/net/thrift_helper.h IDL定义: service ......

一见蓝天 ⋅ 2014/05/02 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

内核线程、轻量级进程、用户线程

线程与进程概念 在现代操作系统中,进程支持多线程。 进程是资源管理的最小单元; 线程是程序执行的最小单元。 即线程作为调度和分配的基本单位,进程作为资源分配的基本单位 一个进程的组成...

117 ⋅ 23分钟前 ⋅ 0

elasticsearch2.4.6升级为elasticsearch-5.5.0的经历

将elasticsearch-5.5.0 中的配置 path.data 指向原来的数据路径 即 path.data: /usr/local/src/elasticsearch-2.4.6/data 注意: elasticsearch-5.5.0 需要将jdk版本升级到1.8...

晨猫 ⋅ 24分钟前 ⋅ 1

lvm讲解 磁盘故障小案例

1

oschina130111 ⋅ 28分钟前 ⋅ 0

那些提升开发人员工作效率的在线工具

本文转载自公众号 Hollis 作为一个Java开发人员,经常要和各种各样的工具打交道,除了我们常用的IDE工具以外,其实还有很多工具是我们在日常开发及学习过程中要经常使用到的。 Hollis偏爱使用...

时刻在奔跑 ⋅ 40分钟前 ⋅ 0

restful风格 实现DELETE PUT请求 的web.xml的配置

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframe......

泉天下 ⋅ 46分钟前 ⋅ 0

Shell数组

Shell数组 Shell在编程方面比Windows批处理强大很多,无论是在循环、运算。 bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数...

蜗牛奔跑 ⋅ 55分钟前 ⋅ 0

nmap为了开发方便 可以做简单的修改

因为nmap扫描是默认使用的是nse脚本,但是在开发的过程中需要修改后缀(主要是因为后缀为lua才能显示高亮,所以这里用一个取巧的办法) nse_main.lua文件中我们找到如下代码 local t, path = cn...

超级大黑猫 ⋅ 59分钟前 ⋅ 0

springmvc获取axios数据为null情况

场景:前端用了vue没有用ajax与后台通信,用了axios,但是在代码运行过程中发现axios传递到后台的值接受到数据为null。 问题原因:此处的问题在与axios返回给后台的数据为json类型的,后台接...

王子城 ⋅ 今天 ⋅ 0

hadoop技术入门学习之发行版选择

经常会看到这样的问题:零基础学习hadoop难不难?有的人回答说:零基础学习hadoop,没有想象的那么难,也没有想象的那么容易。看到这样的答案不免觉得有些尴尬,这个问题算是白问了,因为这个...

左手的倒影 ⋅ 今天 ⋅ 0

806. Number of Lines To Write String - LeetCode

Question 806. Number of Lines To Write String Solution 思路:注意一点,如果a长度为4,当前行已经用了98个单元,要另起一行。 Java实现: public int[] numberOfLines(int[] widths, Str...

yysue ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部