指向数据结构的指针通过以下方式与多个线程共享std::promise
and std::shared_future
。
从书中'C++ 并发实践' 作者:Anthony Williams(第 85-86 页),似乎只有当每个接收线程使用副本时,数据才会正确同步
的std::shared_future
对象而不是每个线程访问单个全局对象std::shared_future
.
为了说明这一点,考虑一个线程创建bigdata
并将指针传递给具有只读访问权限的多个线程。
如果线程之间的数据同步处理不正确,内存重新排序可能会导致未定义的行为(例如,worker_thread
读取不完整的数据)。
这个(不正确?)实现使用单个全局std::shared_future
:
#include <future>
struct bigdata { ... };
std::shared_future<bigdata *> global_sf;
void worker_thread()
{
const bigdata *ptr = global_sf.get();
... // ptr read-only access
}
int main()
{
std::promise<bigdata *> pr;
global_sf = pr.get_future().share();
std::thread t1{worker_thread};
std::thread t2{worker_thread};
pr.set_value(new bigdata);
...
}
在这个(正确的)实现中,每个worker_thread
得到一份副本std::shared_future
:
void worker_thread(std::shared_future<bigdata *> sf)
{
const bigdata *ptr = sf.get();
...
}
int main()
{
std::promise<bigdata *> pr;
auto sf = pr.get_future().share();
std::thread t1{worker_thread, sf};
std::thread t2{worker_thread, sf};
pr.set_value(new bigdata);
....
我想知道为什么第一个版本不正确。
If std::shared_future::get()
是一个非常量成员函数,它是有意义的,因为访问单个std::shared_future
来自多个线程的数据竞争本身就是一场数据竞争。
但由于这个成员函数被声明为 const,并且global_sf
对象与线程同步,从多个线程并发访问是安全的。
我的问题是,为什么只有在每个worker_thread
收到一份副本std::shared_future
?