我试图测试std::shared_future
是如何在不同线程之间共享的,因为这些线程都调用其wait()
函数,并在调用signal
后唤醒。如下:
#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
,运行良好。
然后,我使用普通的future
对象(而不是shared
版本(将auto sf = p.get_future().share();
的行更改为auto sf = p.get_future()
,编译并运行。我得到了同样的结果:虽然我预计对于非共享版本,只有一个线程会成功wait
并返回,而其他线程会挂起。但似乎程序运行正常。
所以我的问题是:我们什么时候需要使用std::shared_future
而不是std::future
?或者它只是一个像std::shared_ptr
这样的对象,作为std::future
的一个简单包装器,以便它可以被传递?
我的意思是,是否存在不共享的未来不能满足需求或场景的情况。你能帮忙解释一下吗?
;共享的";CCD_ 14的一部分不是关于等待,而是关于get。
我预计对于非共享版本,只有1个线程将成功等待并返回,而其他线程将挂起。
不,这是完全安全的,您可以等待任意多个线程的未来(它是const成员,因此是线程安全的(,并且在设置结果时所有线程都必须取消阻止。但请注意,wait()
不能在有人呼叫get()
之后呼叫。
不同之处在于你如何得到结果。请记住,std::future
代表由std::promise
设置的未来结果。
std::future::get()
按值返回。它只能调用一次,因此只能从一个线程调用std::shared_future::get()
返回一个常量引用。它可以从多个线程调用多次。当然,要小心底层对象的线程安全性——它的方法是否真的是线程安全的
此外,std::shared_future
可以被克隆,并且多个这样的对象可以引用单个共享状态,即链接到单个承诺对象。只要某个未来/承诺指向共享状态,共享状态就会存在,比如std::shared_ptr<State>
。
在您的情况下,您稍微滥用了std::shared_future sf
,每个等待结果的线程都应该获得自己的克隆。这样,它的寿命是安全的。设想的工作流程是:
std::promise
被创建,从中获得[第一个]future
- 承诺是给生产者的,消费者并不知道
- 未来交给了[每个]消费者[他们可以克隆它,并在必要时传递它]
我的意思是,在任何情况下,非共享的未来都不能满足需求或场景。你能帮忙解释一下吗?
有两个使用者线程,都在等待结果。CCD_ 26将需要恰好一个线程来调用CCD_ 27并以某种方式与另一个线程共享该结果。尽管两者都可以调用CCD_ 28。另一方面,CCD_;视图";结果,因为它是常量。是的,如果需要传递,必须复制结果,但这无论如何都是不可避免的。
除了复制之外,std::shared_future的一个副本不能从不同的线程中使用。每个线程都必须有自己的std::shared_future副本。
https://en.cppreference.com/w/cpp/thread/shared_future
如果每个线程都通过自己的shared_future对象副本访问同一共享状态,那么从多个线程访问同一个共享状态是安全的。