【并发编程十一】c++线程同步——future-创新互联
【并发编程十一】c++线程同步——future
名称栏目:【并发编程十一】c++线程同步——future-创新互联
本文地址:http://hbruida.cn/article/cogdjg.html
- 一、互斥
- 二、条件变量
- 三、future
- 1、promise
- 1.1、子线程设值,主线程获取
- 1.2、主线程设置值,子线程获取
- 2、async
- 2.1、不开新线程的async
- 2.2、开新线程的async
- 3、packaged_task
- 3.1、不使用bind
- 3.2、提前指定参数
- 3.3、bind
- 4、shared_future
- 四、信号量
简介:
本篇文章,我们详细的介绍下c++标准库提供的线程同步方法中的第3个——future。
参见【并发编程九】c++线程同步——互斥(mutex)
二、条件变量参见【并发编程十】c++线程同步——条件变量(condition_variable)
三、future类模板 std::future 提供访问异步操作结果的机制:
- (通过std::async、std::packaged_task或std::promise创建的)异步操作能提供一个 std::future 对象给该异步操作的创建者。
- 然后,异步操作的创建者能用各种方法查询、等待或从 std::future 提取值。若异步操作仍未提供值,则这些方法可能阻塞。
- 异步操作准备好发送结果给创建者时,它能通过修改链接到创建者的 std::future 的共享状态(例如 std::promise::set_value )进行。
注意, std::future 所引用的共享状态不与另一异步返回对象共享(与 std::shared_future 相反)。
1、promise- 类模板 std::promise 提供存储值或异常的设施,之后通过 std::promise 对象所创建的 std::future 对象异步获得结果。注意 std::promise 只应当使用一次。
备注:简单来说,就是以下过程
- 1、把promis和future绑定。
- 2、promise设置值后,
- 3、future等待,直到获取值。
- demo
#include#include#includeusing namespace std;
void task(int a, int b, promise& p)
{p.set_value(a + b);
}
int main()
{// 把promise和future做关联
promisep;
futuref=p.get_future();
thread task1(task,1,2,ref(p));
//do somesthing
//get promise value
f.wait();
cout<< "return value is "<< f.get()<< '\n';//只能get一次。
task1.join();
}
- 输出
1.2、主线程设置值,子线程获取
- demo
#include#include#includeusing namespace std;
void task(int a, future& b, promise& p)
{p.set_value(a + b.get());
}
int main()
{// 把promise和future做关联
promisep_ret;
futuref_ret=p_ret.get_future();
promisep_in;
futuref_in = p_in.get_future();
thread task1(task,1,ref(f_in),ref(p_ret));
//do somesthing
//...
p_in.set_value(3);
//get promise value
f_ret.wait();
cout<< "return value is "<< f_ret.get()<< '\n';//只能get一次。
task1.join();
}
- 输出
2、async
异步运行一个函数(有可能在新线程中执行),并返回保有其结果的 std::future.
2.1、不开新线程的async- demo
#include#include#includeusing namespace std;
int task(int a, int b)
{return a + b;
}
int main()
{// 把async和future做关联
futuref = async(task, 1, 5);
//get future value
f.wait();
cout<< "return value is "<< f.get()<< '\n';
}
- 输出
2.2、开新线程的async
- launch::async意思是创建新的线程。
- launch::deferred和不传默认参数是一样的,相当于延时调用。
#include#include#includeusing namespace std;
int task(int a, int b)
{return a + b;
}
int main()
{// 把async和future做关联
futuref = async(launch::async,task, 1, 5);
//get future value
f.wait();
cout<< "return value is "<< f.get()<< '\n';
}
3、packaged_task输出结果和不开线程一样的
- 打包一个函数,存储其返回值以进行异步获取
- demo
#include#include#includeusing namespace std;
int task(int a, int b)
{return a + b;
}
int main()
{// 调用packaged_task的构造函数,返回值和两个参数都是int类型,
packaged_taskt(task);
//执行
t(5,5);
// 把packaged_task和future做关联
futuref = t.get_future();
//获取返回值的结果
f.wait();
cout<< "return value is "<< f.get()<< '\n';
}
输出
3.2、提前指定参数
#include#include#includeusing namespace std;
int task(int a, int b)
{return a + b;
}
int main()
{// 调用packaged_task的构造函数,返回值和两个参数都是int类型,
packaged_taskt(std::bind(task,11,12));
//执行
t();
// 把packaged_task和future做关联
futureresult = t.get_future();
//获取返回值的结果
result.wait();
cout<< "return value is "<< result.get()<< '\n';
}
- 输出
3.3、bind
bind返回参数为std::function
- demo
#include#include#includeusing namespace std;
int task(int a, int b)
{return a + b;
}
int main()
{// bind返回值为std::function,
auto a = bind(task, 11, 14);
//执行
int result = a();
cout<< "return value is "<< result<< '\n';
}
- 输出
备注:既然bind就可以获取结果,为何还要用packaged_task,当然是因为future啊。
4、shared_future- future只能get一次,那如果我们想用使用多次的get呢?———答:使用shared_future。
- 网上的例子基本都是shared_future和async放在一起使用。
- 网上并没有shared_future和promise一起使用的例子,所以我们写下后者的例子demo.
#include#include#includeusing namespace std;
mutex mtx;
void task(int a, shared_future& b, promise& p)
{p.set_value(2);
b.wait();
int bb = b.get();
lock_guardguard(mtx);
cout<< "task b ="<< b.get()<// 把promise和future做关联
promisep_ret_1,p_ret_2;
futuref1 = p_ret_1.get_future();
futuref2 = p_ret_2.get_future();
promisep_in;
shared_futures_f = p_in.get_future();
thread task1(task, 1, ref(s_f), ref(p_ret_1));
thread task2(task, 2, ref(s_f), ref(p_ret_2));
//do somesthing
f1.wait();
f2.wait();
//...
p_in.set_value(3);
//get promise value
{lock_guardguard(mtx);
cout<< "main() return value is "<< f1.get()<< '\n';//只能get一次。
cout<< "main() return value is "<< f2.get()<< '\n';//只能get一次。
}
task1.join();
task2.join();
}
- 输出
参考:
1、https://www.apiref.com/cpp-zh/cpp/thread.html
2、https://en.cppreference.com/w/cpp/thread
3、书籍《c++服务器开发精髓》——张远龙
- 参见【并发编程十二】c++20线程同步——信号量(semaphore)
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
名称栏目:【并发编程十一】c++线程同步——future-创新互联
本文地址:http://hbruida.cn/article/cogdjg.html