我尝试测试 std::shared_future
如何在不同线程之间共享,因为这些线程都调用其 wait()
函数,并在其 后唤醒调用信号
。如下:
#include <iostream>
#include <future>
using namespace std;
int main() {
promise<void> p, p1, p2;
auto sf = p.get_future().share(); // This line
auto f1 = [&]() {
p1.set_value();
sf.wait();
return 1;
};
auto f2 = [&]() {
p2.set_value();
sf.wait();
return 2;
};
auto ret1 = async(launch::async, f1);
auto ret2 = async(launch::async, f2);
p1.get_future().wait();
p2.get_future().wait();
p.set_value();
cout << ret1.get() << ", " << ret2.get();
return 0;
}
程序打印 1, 2
并且工作正常。
然后我使用 oridinay 将
对象,而不是auto sf = p.get_future().share();
行更改为 auto sf = p.get_future()
futureshared
版本,编译并运行。我得到了相同的结果:虽然我预计对于非共享版本,只有 1 个线程将成功等待并返回,而其他线程将挂起。但看起来程序仍然运行正常。
所以我的问题是:我们什么时候需要使用 std::shared_future
而不是 std::future
?或者它只是像 std::shared_ptr
这样的对象,作为 std::future
的简单包装,以便可以传递?
我的意思是,在任何情况下,非共享 future 都不能满足需求或场景。能帮忙解释一下吗?
最佳答案
shared_future
的“共享”部分重要的不是等待,而是得到。
I expected that for the non-shared version, only 1 thread will successfully wait and return while other threads will hang.
不,这是完全安全的,您可以根据需要从任意多个线程等待 future (它是 const 成员,因此是线程安全的),并且在设置结果时所有线程都必须解除阻塞。但请注意 wait()
有人调用 get()
后无法再调用.
区别在于获得结果的方式。请记住,std::future
代表 std::promise
设定的 future 结果.
-
std::future::get()
按值返回。它只能被调用一次,因此只能从一个线程调用。 -
std::shared_future::get()
返回常量引用。它可以从多个线程多次调用。当然要小心底层对象的线程安全性——它的方法是否真的是线程安全的。
此外std::shared_future
可以被克隆,并且多个此类对象可以引用单个共享状态,即链接到单个 promise 对象。只要有一些 future/promise 指向它,共享状态就存在,比如 std::shared_ptr<State>
.
就您而言,您稍微误用了 std::shared_future sf
,每个等待结果的线程都应该得到自己的克隆。这样,它的生命周期就是安全的。设想的工作流程是:
-
std::promise
创建后,[第一个]future
从中获得。 - promise 是给生产者的,消费者并不知道。
- future 被赋予[每个]消费者[他们可以克隆它并在必要时传递它]。
I mean is there any case that non-shared future doesn't fulfill the need or scenario. Would you help to explain?
有两个消费者线程,都在等待结果。 std::future
需要一个线程来调用 get
并以某种方式与他人分享该结果。尽管两者都可以调用 wait()
。另一方面std::shared_future
允许两者“查看”结果,因为它是常量。是的,如果需要传递结果,就必须复制结果,但无论如何这是不可避免的。
关于c++ - 我们什么时候需要 std::shared_future 而不是 std::future 来进行线程间同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73835444/