async
和
promise
的相关使用总结。
st::async( Function&& f, Args&&... args );
或者async( std::launch policy, Function&& f, Args&&... args );
std::launch::async | std::launch::deferred
,这种策略标示async
产生的线程有两种执行方式:一种为线程独立执行,另一种为当主线程或者调用者线程中执行std::future::get
的成员函数时会执行产生的线程。std::async(std::launch::async,f,x)
形式),则在async初始化所有线程局域对象之后会执行函数f。std::async(std::launch::deferred,f,x)
),则async同样会使用std:thread
构造函数的方式转换f
和args
参数,但是并不会产生执行线程。此时它会进行惰性求值,即当async函数返回的std::future
对象进行get
取值的时候才会执行线程获取结果。std::async
所创建的共享状态的对象 std::future
查看如下代码
#include
#include
#include
#include
#include
#include
#include std::mutex m;
struct X { void foo(int i, const std::string& str) { std::lock_guard<std::mutex> lk(m);std::cout << str << ' ' << i << '
';}void bar(const std::string& str) { std::lock_guard<std::mutex> lk(m);std::cout << str << '
';}int operator()(int i) { std::lock_guard<std::mutex> lk(m);std::cout << i << '
';return i + 10;}
};template <typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{ auto len = end - beg;if (len < 1000)return std::accumulate(beg, end, 0);RandomIt mid = beg + len/2;auto handle = std::async(std::launch::async,parallel_sum<RandomIt>, mid, end);int sum = parallel_sum(beg, mid);return sum + handle.get();
}int main()
{ std::vector<int> v(10000, 1);std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '
';X x;// 以默认策略调用 x.foo(42, "Hello") :// 可能同时打印 "Hello 42" 或延迟执行,这里策略默认是std::launch::async|std::launch::deferred//即a1的打印可能在主线程打印的任何时候auto a1 = std::async(&X::foo, &x, 42, "Hello");// 以 deferred 策略调用 x.bar("world!")// 调用 a2.get() 或 a2.wait() 时打印 "world!"auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");// 以 async 策略调用 X()(43) :// 同时打印 "43"auto a3 = std::async(std::launch::async, X(), 43);a2.wait(); // 打印 "world!"std::cout << a3.get() << '
'; // 打印 "53"
} // 若 a1 在此点未完成,则 a1 的析构函数在此打印 "Hello 42"
因为a1可能是立即执行,也有可能是惰性求值,所以a1对象的打印可能遍布整个打印的不同时间段。
a2则是惰性求值,当调用a2.wait()
或者a2.get()
求值的时候会获取a2的函数返回值
a3同样为异步求值,同时也能够支持get,只是get()会晚于线程执行之后。
输出如下:
第一种
he sum is 10000
world!
Hello 42
43
53
第二种
The sum is 10000
43
Hello 42
world!
53
第三种
The sum is 10000
Hello 42
43
world!
53
template< class R > class promise
空模版template< class R > class promise
非void特化,用于线程之间交流对象template<> class promise
用于交流无状态事件promise
对共享状态做三件事: 构造函数
a.promise();
默认构造函数,构造一个共享状态为空的 std::promise
b.template< class Alloc > promise( std::allocator_arg_t, const Alloc& alloc )
构造一个共享状态为空的 std::promise,由 alloc 分配共享状态
c.promise( promise&& other ) noexcept
移动构造函数,用原属 other 的共享状态构造新的 std::promise 对象,使用移动语义。构造完毕后, other 无共享状态;
d.promise( const promise& other ) = delete;
std::promise 不可复制
析构函数
~promise()
两种情况调用析构函数
a.若共享状态就绪,则释放它。
b.若共享状态未就绪,则存储以 std::future_errc::broken_promise 为 error_condition 的 std::future_error 类型异常对象,令共享状态就绪再释放它。
赋值运算符
promise& operator=( promise&& other ) noexcept
移动赋值运算符。首先析构原共享状态,然后如同以执行std::promise(std::move(other)).swap(*this)
对共享状态赋
promise& operator=( const promise& rhs ) = delete
std::promise 不可复制赋值
std::promise
返回与 *this 关联同一状态的 future 对象
std::promise
更新 promise 对象时获得单个与 promise 对象关联的互斥量, 若无共享状态或共享状态已存储值或异常,则抛出异常。对此函数的调用和对 get_future 的调用不会造成数据竞争。
查看如下代码,此时并不会造成对共享变量对竞争。
#include
#include
#include
#include using namespace std;int fun1(std::future<int> &f) { int res = 1;int n = f.get();for (int i = n; i>1; --i) { res *=i;}cout << "Result is " << res << endl;return res;
}int main()
{ int x;//std::thread t1(fun1,4,std::ref(x));//t1.join();std::promise<int> p;//标示f是一个需要从未来获取数值future对象std::future<int> f = p.get_future(); std::future<int> fu = std::async(std::launch::async,fun1, std::ref(f));//为f设置数值,在子线程中进行f.get()获取主线程到数值p.set_value(4);x = fu.get();cout << "Get from child " << x << endl;return 0;
}
输出如下:
Result is 24
Get from child 24
std::promise
原子地存储 value 到共享状态,而不立即令状态就绪。在当前线程退出时,销毁所有拥有线程局域存储期的对象后,再令状态就绪。即当创建的线程执行结束之前设置共享变量返回调用线程。
代码如下:
#include
#include
#include int main()
{ //using namespace std::chrono_literals;std::promise<int> p;std::future<int> f = p.get_future();//在线程执行结束要离开之前设置共享状态,设置之前等待1s//并返回给线程调用者主线程中的f.wait获取值std::thread([&p] { std::this_thread::sleep_for(std::chrono::seconds(1));p.set_value_at_thread_exit(9);}).detach();std::cout << "Waiting..." << std::flush;f.wait();std::cout << "Done!
Result is: " << f.get() << '
';
}
输出如下:
Waiting...Done!
Result is: 9
std::promise
存储异常指针 p 到共享状态中,并令状态就绪
主要用来进行线程异常情况的存储,同时将异常情况传出到调用线程进行处理
如下代码
#include
#include
#include int main()
{ std::promise<int> p;std::future<int> f = p.get_future();std::thread t([&p]{ try { // 可能抛出的代码throw std::runtime_error("Example");} catch(...) { try { // 存储任何抛出的异常于 promise,设置异常值到共享状态并传出p.set_exception(std::current_exception());} catch(...) { } // set_exception() 亦可能抛出}});try { //获取一异常的共享状态std::cout << f.get();} catch(const std::exception& e) { std::cout << "Exception from the thread: " << e.what() << '
';}t.join();
}
输出如下:
Exception from the thread: Example
std::promise
存储异常指针 p 到共享状态中,而不立即使状态就绪。在当前线程退出时,销毁所有拥有线程局域存储期的变量后,再零状态就绪。
async
提供异步操作,可以支持线程异步执行或者惰性求值来达到对线程执行情况以及共享变量获取时机的控制。即我想要获取变量,使用async
的std::launch::deferred
让线程future对象想要获取线程函数结果时再进行线程的执行返回,在此期间线程函数即可处于休眠,依此提供异步线程共享变量机制。
而promise
类则提供一种共享状态的访问机制,多线程之间的状态共享可以通过promise
类对象的get_future
监控数据的共享状态,set_value
以及set_value_exit
等成员函数设置数据的共享状态且内部保证不会产生对共享数据的竞争问题,依此来提供安全使用便捷的多线程之间数据的访问机制。
经过长期探索,发现一个不需要手动设置线程休眠时间(e.g. std::this_thread::sleep_for(std::chrono::microseconds(1)))的代码: Github: https://github.com/log4cplus/ThreadPool #ifndef THREAD_POOL_H_7e...
nth_element(first,nth,last) first,last 第一个和最后一个迭代器,也可以直接用数组的位置。 nth,要定位的第nn 个元素,能对它进行随机访问. 将第n_thn_th 元素放到它该放的位置上,左边元素都小于它,右边元素都大于它. 测试代码: http://www.cplusplus.com...
c/c++老版本的rand()存在一定的问题,在转换rand随机数的范围,类型或者分布时,常常会引入非随机性。
定义在
jsoncpp 是一个C++ 语言实现的json库,非常方便得支持C++得各种数据类型到json 以及 json到各种数据类型的转化。 一个json 类型的数据如下: {"code" : 10.01,"files" : "","msg" : "","uploadid" : "UP000000" } 这种数据类型方便我们人阅读以...
问题如下: 已知一组数(其中有重复元素),求这组数可以组成的所有子集中,子 集中的各个元素和为整数target的子集,结果中无重复的子集。 例如: nums[] = [10, 1, 2, 7, 6, 1, 5], target = 8 结果为: [[1, 7], [1, 2, 5], [2, 6], [1, 1, 6]] 同样之前有...
Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷。 定义 Promise 是一个对象,它用来标识 JavaScript 中异步操作的状态(pending, resolve, reject)及结果(data)。 从控制台打印出来一个Promise 对象...
1.Promise 基础知识梳理 创建一个Promise实例 const promise = new Promise(function(resolve, reject) {if (success){resolve(value);} else {reject(error);} }); Promise构造函数接受一个函数作为参数...
在 Vue.js项目中使用Vuex,Vuex 依赖 Promise,所以如果你的浏览器没有实现 Promise (比如 IE),那么就需要使用一个 polyfill 的库 我们可以通过babel-profill转译 1、安装 npm install --save-dev babel-polyfill 2、在main.js中引入...
关于如何在有噪声的数据中进行状态估计的问题的理解,状态估计的问题是指在运动和观测方程中,通常假设两个噪声ωiomega_i和υk,jupsilon_{k,j}满足零均值的高斯分布, xk=f(xk−1,uk)+ωkx_k=f(x_{k-1},u_k)+omega_k其中ωk→N(0,Rk)omega_k ightarro...
强化学习(英语:Reinforcement learning,简称RL)是机器学习中的一个领域,强调如何基于环境而行动,以取得最大化的预期利益。其灵感来源于心理学中的行为主义理论,即有机体如何在环境给予的奖励或惩罚的刺激下,逐步形成对刺激的预期,产生能获得最大利益的习惯性行为。这个方法具有普适性,因此在其他许多领域都有研究,例如博弈...
文章目录PG 的状态机和peering过程1. PG 状态机变化的时机2. pg的状态演化过程3. pg状态变化实例讲解3.1 pg状态的管理结构3.2 数据的pg状态变化过程3.2.1 NULL -> initial3.2.2 initial -> reset -> Started3.2.3 Started(start) ->St...
什么是状态模式? 定义:将事物内部的每个状态分别封装成类,内部状态改变会产生不同行为。 主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。 何时使用:代码中包含大量与对象状态有关的条件语句。 如何解决:将各种具体的状态类抽象出来。 应用实例: 1、打篮球的时候运动员可以有正常状态、不正常状态和超...
别小看这个功能, 感觉在写一些技术 Blog 的情况下还是挺有用的. 打开QQ拼音: 输入法设置->基本设置->初始状态->中文状态下使用英文标点. 转载于:https://www.cnblogs.com/qrlozte/p/4904087.html...