Yas*_*suo 13 c++ multithreading asynchronous language-lawyer c++17
根据C++17标准,这个程序的输出是什么?
#include <iostream>
#include <string>
#include <future>
int main() {
std::string x = "x";
std::async(std::launch::async, [&x]() {
x = "y";
});
std::async(std::launch::async, [&x]() {
x = "z";
});
std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)
程序保证输出:z?
Evg*_*Evg 17
C++ 参考明确提到了此代码的行为:
如果
std::future
获取的 fromstd::async
未从引用移动或绑定到引用,则 the 的析构函数std::future
将在完整表达式的末尾阻塞,直到异步操作完成,本质上使代码如以下同步:
Run Code Online (Sandbox Code Playgroud)std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f() std::async(std::launch::async, []{ g(); }); // does not start until f() completes
因此您的代码可以保证打印z
- 不存在数据争用。
我不认为 cppreference 在这种情况下完全准确。
\n标准规定 dtor 会std::future
释放任何共享状态 (\xc2\xa7[futures.unique_future]/9):
\n\n〜未来();
\n
\n效果:\n
\n- 释放任何共享状态(31.6.5);
\n- 破坏
\n*this
.
释放共享状态的描述是这样的(\xc2\xa7[futures.state]/5):
\n\n\n当异步返回对象或异步提供者被称为释放其共享状态时,这意味着:
\n\n
\n- 如果返回对象或提供者持有对其共享状态的最后一个引用,则共享状态将被销毁;和
\n- 返回对象或提供者放弃对其共享状态的引用;和
\n- 这些操作不会阻止共享状态变为就绪状态,但如果满足以下所有条件,则可能会阻塞:共享状态是通过调用创建的
\nstd::async
,共享状态尚未就绪,并且这是最后一个引用到共享状态。
[强调]
\n本质上,代码具有未定义的行为。虽然允许实现生成代码来阻塞共享状态以准备就绪,但不需要这样做,甚至不需要记录它是否会这样做。因此,您所遇到的情况几乎是未定义行为的典型情况:您可能会得到您所期望的结果,但这不是必需的。
\n我引用了 N4713,它(如果没记错的话)几乎是 C++17 标准。看起来至少在 N4950(几乎是 C++23)之前,措辞都保持不变。
\n 归档时间: |
|
查看次数: |
1344 次 |
最近记录: |