5go*_*der 17 concurrency multithreading asynchronous language-lawyer c++11
在他的"C++编程语言"(第4版)一书的"教程"一章5.3.5.3中,Bjarne Stroustrup撰写了关于该std::async功能的文章.
有一个明显的局限性:甚至不要考虑使用
async()共享需要锁定的资源的任务 -async()你甚至不知道thread将使用多少个,因为这async()可以根据它对可用系统资源的了解来决定在通话时.
类似的劝告可以在他的网站上的C++ 11-FAQ中找到.
"简单"是
async()/future设计最重要的方面; 期货也可以用在一般线程使用,但是甚至不认为使用async()来启动该做的我的任务/ O,操纵互斥体,或者以其他方式与其他任务进行交互.
有趣的是,当他在他的书的第42.4.6节中更详细地回到C++ 11的并发特性时,他没有详细说明这个限制.更有趣的是,在本章中他实际上还在继续(与他网站上的陈述相比):
一个简单而实际的用法
async()是生成一个任务来收集用户的输入.
asyncon 的文档cppreference.com根本没有提到任何这样的限制.
在阅读了导致最终形式的C++ 11标准的一些提议和讨论之后(遗憾的是我无法访问),我明白它async已经很晚才纳入C++ 11标准并且有很多讨论这个功能应该有多强大.特别是,我发现了文章中的Async Tasks in C++ 11:Not Quite There Yet Bartosz Milewski对实现时必须考虑的问题进行了非常好的总结async.
但是,所有讨论的问题都与thread_local如果线程被回收时未被破坏的变量,虚假死锁或数据访问违规有关,如果线程在操作中切换其任务并且两个任务分别持有mutex或recursive_mutex等等.这些都为特征的实现者严重关切,但如果我理解正确的话,目前规范async要求所有这些细节被执行或者在调用者线程或任务对用户隐藏的,如果作为一个新线程的任务创建.
所以我的问题是:我不允许做什么async,我被允许thread手动使用s,这个限制的原因是什么?
例如,以下程序有什么问题吗?
#include <future>
#include <iostream>
#include <mutex>
#include <vector>
static int tally {};
static std::mutex tally_mutex {};
static void
do_work(const int amount)
{
for (int i = 0; i < amount; ++i)
{
// Might do something actually useful...
const std::unique_lock<std::mutex> lock {tally_mutex};
tally += 1;
}
}
int
main()
{
constexpr int concurrency {10};
constexpr int amount {1000000};
std::vector<std::future<void>> futures {};
for (int t = 0; t < concurrency; ++t)
futures.push_back(std::async(do_work, amount / concurrency));
for (auto& future : futures)
future.get();
std::cout << tally << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
显然,如果运行时决定在主线程上安排所有任务,我们将毫无理由地一遍又一遍地不必要地获取互斥锁.但虽然这可能效率低下,但并非不正确.
std :: async的"问题"是默认情况下你不知道它是否启动一个线程.如果你的函数需要在一个单独的线程上运行,那么这是一个问题,因为在调用get()或wait()之前你的函数可能不会运行.你可以传递std :: launch :: async来确保函数在它自己的线程上启动,这就像一个不能分离BG的std :: thread.
| 归档时间: |
|
| 查看次数: |
984 次 |
| 最近记录: |