c++ - C++ 中是否存在任何隐式内存屏障
问题描述
在下面的代码中,是使用必要的原子来保证所有平台上的无竞争语义,还是使用 promise.set_value/future.wait 暗示某种隐式内存屏障,允许我依赖标志写入外螺纹可见吗?
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() 或期货之类的东西,标准是否保证了任何“隐式”内存屏障?
解决方案
thread.join()
和promise.set_value()
/future.wait()
保证暗示记忆障碍。
atomic_bool
如果您不希望编译器使用其他代码重新排序布尔检查或赋值,则使用是必要的。但在那种特殊情况下,您可以使用 not atomic bool
。如果您不在任何其他地方使用它,那flag
将保证在检查时进行,因为分配和检查位于同步点 ( ) 的相对侧(强制编译器加载实际值)和函数保证只有在 lambda 执行后才能完成。true
fut.get()
flag
runInThreadPoolBlocking()
引用cplusplus.com的内容future::get()
,例如:
数据竞赛
未来对象被修改。共享状态作为原子操作访问(不会导致数据竞争)。
对于promise::set_value()
. 除了其他东西
... 原子操作(不会导致数据争用) ...
意味着没有一个冲突的评估发生在另一个之前(严格的内存排序)。
所有std::
多线程同步原语和工具也是如此,您希望某些操作仅在同步点之前或之后发生(如std::mutex::lock()
or unlock()
、thread::join()
等)。
请注意,线程对象本身的任何操作都不会与之同步thread::join()
(与它所代表的线程内的操作不同)。
推荐阅读
- python - 如何一次在 RAM 中保存包含数百万个字典的 python 列表?
- java - Spring security OAuth2: permitAll() 对我不起作用(HTTP 401 for unprotected endpoints)
- java - 将包含子目录和 java 文件的 2 个顶级目录编译成 java jar 文件 UNIX
- oracle - 在 Oracle 中将小时数添加到时间数据类型
- java - 如何复制一个对象(在这种情况下是一个数组列表)然后只清除其中一个
- java - 在 Selenium 中,使用 CRTL + Shift + N 以隐身模式启动浏览器在 Sauce Labs 中不起作用
- powershell - 将文件内容与 Powershell 中的字符串进行比较
- java - 在 Google Data Flow 上的 Spring Boot 项目中运行 Apache Beam 管道
- android - 使用 Query 或使用 Normal Reference 哪个更好 Firebase
- linux - 为什么我需要在安装我的二进制文件后设置 LD_LIBRARY_PATH?