C ++中是否存在任何隐式内存障碍
Are there any implicit memory barriers in C++
在下面的代码中,是使用必要的原子来保证所有平台上的无竞争语义,还是使用承诺。set_value/future。等待暗示某种隐式内存屏障允许我要依靠外线程可见的标志写入?
std::atomic_bool flag{false}; // <- does this need to be atomic?
runInThreadPoolBlocking([&]() {
// do something
flag.store(true);
});
if (flag.load()) // do something
// simplified runInThreadPoolBlocking implementation
template <typename Callable>
void runInThreadPoolBlocking(Callable func)
{
std::promise<void> prom;
auto fut = prom.get_future();
enqueueToThreadPool([&]() {
func();
prom.set_value();
});
fut.get();
}
一般来说,对于 thread.join() 或 futures 之类的东西,是否存在标准保证的任何 "implicit" 内存障碍?
thread.join()
和 promise.set_value()
/future.wait()
保证暗示内存障碍。
如果您不希望编译器使用其他代码重新排序布尔检查或赋值,则必须使用 atomic_bool
。但在那种特殊情况下,您可以使用非原子 bool
。如果你不在任何其他地方使用它,那么 flag
在检查的那一刻将保证是 true
,因为赋值和检查在同步点的相对侧(fut.get()
)(强制编译器加载真实的 flag
值)并且函数 runInThreadPoolBlocking()
保证仅在执行 lambda 后完成。
引用自cplusplus.com for future::get()
,例如:
Data races
The future object is modified. The shared state is accessed as an
atomic operation (causing no data races).
promise::set_value()
也是如此。除了其他东西
... atomic operation (causing no data races) ...
意味着没有一个冲突的评估发生在另一个之前(严格的内存排序)。
所有 std::
多线程同步原语和工具也是如此,您希望某些操作仅在同步点之前或之后发生(如 std::mutex::lock()
或 unlock()
、thread::join()
, 等等).
请注意,对线程对象本身的任何操作都不会与 thread::join()
同步(不同于它所代表的线程内的操作)。
std::atomic_bool flag{false}; // <- does this need to be atomic?
是.
来电:
prom.get_future()
returns 一个 std::future<void>
对象。
对于未来,参考资料如下:
The class template std::future provides a mechanism to access the
result of asynchronous operations:
An asynchronous operation (created via std::async, std::packaged_task, or std::promise) can provide a std::future object
to the creator of that asynchronous operation.
The creator of the asynchronous operation can then use a variety of methods to query, wait for, or extract a value from the
std::future. These methods may block if the asynchronous operation has
not yet provided a value.
When the asynchronous operation is ready to send a result to the creator, it can do so by modifying shared state (e.g.
std::promise::set_value) that is linked to the creator's std::future.
Note that std::future references shared state that is not shared with any other asynchronous return objects (as opposed to
std::shared_future).
您没有在此处存储 'return' 值,因此这一点有点无语,并且由于没有其他保证(并且整个想法是线程可能 运行 并行!) 如果它是共享的,你需要保持 bool 的原子性!
在下面的代码中,是使用必要的原子来保证所有平台上的无竞争语义,还是使用承诺。set_value/future。等待暗示某种隐式内存屏障允许我要依靠外线程可见的标志写入?
std::atomic_bool flag{false}; // <- does this need to be atomic?
runInThreadPoolBlocking([&]() {
// do something
flag.store(true);
});
if (flag.load()) // do something
// simplified runInThreadPoolBlocking implementation
template <typename Callable>
void runInThreadPoolBlocking(Callable func)
{
std::promise<void> prom;
auto fut = prom.get_future();
enqueueToThreadPool([&]() {
func();
prom.set_value();
});
fut.get();
}
一般来说,对于 thread.join() 或 futures 之类的东西,是否存在标准保证的任何 "implicit" 内存障碍?
thread.join()
和 promise.set_value()
/future.wait()
保证暗示内存障碍。
如果您不希望编译器使用其他代码重新排序布尔检查或赋值,则必须使用 atomic_bool
。但在那种特殊情况下,您可以使用非原子 bool
。如果你不在任何其他地方使用它,那么 flag
在检查的那一刻将保证是 true
,因为赋值和检查在同步点的相对侧(fut.get()
)(强制编译器加载真实的 flag
值)并且函数 runInThreadPoolBlocking()
保证仅在执行 lambda 后完成。
引用自cplusplus.com for future::get()
,例如:
Data races
The future object is modified. The shared state is accessed as an atomic operation (causing no data races).
promise::set_value()
也是如此。除了其他东西
... atomic operation (causing no data races) ...
意味着没有一个冲突的评估发生在另一个之前(严格的内存排序)。
所有 std::
多线程同步原语和工具也是如此,您希望某些操作仅在同步点之前或之后发生(如 std::mutex::lock()
或 unlock()
、thread::join()
, 等等).
请注意,对线程对象本身的任何操作都不会与 thread::join()
同步(不同于它所代表的线程内的操作)。
std::atomic_bool flag{false}; // <- does this need to be atomic?
是.
来电:
prom.get_future()
returns 一个 std::future<void>
对象。
对于未来,参考资料如下:
The class template std::future provides a mechanism to access the result of asynchronous operations:
An asynchronous operation (created via std::async, std::packaged_task, or std::promise) can provide a std::future object to the creator of that asynchronous operation.
The creator of the asynchronous operation can then use a variety of methods to query, wait for, or extract a value from the std::future. These methods may block if the asynchronous operation has not yet provided a value.
When the asynchronous operation is ready to send a result to the creator, it can do so by modifying shared state (e.g. std::promise::set_value) that is linked to the creator's std::future.
Note that std::future references shared state that is not shared with any other asynchronous return objects (as opposed to std::shared_future).
您没有在此处存储 'return' 值,因此这一点有点无语,并且由于没有其他保证(并且整个想法是线程可能 运行 并行!) 如果它是共享的,你需要保持 bool 的原子性!