帮忙贴下您的运行结果
顺便说明下您使用的操作系统和编译器及其版本,谢谢了。
#include <chrono>
#include <future>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
std::mutex g_display_mutex;
void PrintThreadId() {
std::this_thread::sleep_for(std::chrono::seconds(2));
{
std::lock_guard<std::mutex> lock(g_display_mutex);
std::cout << std::this_thread::get_id() << std::endl;
}
}
int main(int argc, char* argv[]) {
std::vector<std::future<void>> futures;
for (int i = 0; i < 10; ++i) {
futures.emplace_back(std::async([]{
return PrintThreadId();
}));
}
for (std::future<void>& future : futures) {
future.wait();
}
}
[解决办法]
vegertar@mac:/tmp$ uname -a
Darwin mac.vegertar 13.0.0 Darwin Kernel Version 13.0.0: Thu Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64
vegertar@mac:/tmp$ c++ -v
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix
vegertar@mac:/tmp$ c++ -std=c++11 a.cc
vegertar@mac:/tmp$ ./a.out
0x10e4b2000
0x10e42f000
0x10e3ac000
0x10e535000
0x10e5b8000
0x10e63b000
0x10e6be000
0x10e741000
0x10e7c4000
0x10e847000
[解决办法]
我Mac OSX上面Clang++编译运行的。
oughtlast-lm:c++11 zmyu$ clang++ cc.cpp -std=c++11 -stdlib=libc++
oughtlast-lm:c++11 zmyu$ ./a.out
0x1079db000
0x107a5e000
0x107958000
0x107ae1000
0x107b64000
0x107c6a000
0x107be7000
0x107ced000
0x107d70000
0x107df3000
oughtlast-lm:c++11 zmyu$
[解决办法]
2008R2 VS2013
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x64
D:\temp>b.exe
9396
9044
1116
14016
5584
10320
11916
19536
13688
11116
[解决办法]
ubuntu 10.04 g++-4.8.0
3077957328
3077957328
3077957328
3077957328
3077957328
3077957328
3077957328
3077957328
3077957328
3077957328
想要多线程的话,必须这样写。
futures.emplace_back(std::async(std::launch::async, []{
return PrintThreadId();
}));
再次运行的话,输出如下。
3078294384
3069901680
3059411824
3034233712
3042626416
3051019120
3017448304
3025841008
3009055600
3000662896
3078301392
注意 async 的第一个参数需要明确指明 launch::async。这是因为
c++11 30.6.8/3 states
The first function behaves the same as a call to the second function with a policy argument of launch::async
[解决办法]
launch::deferred and the same arguments for F and Args. ... The further behavior of the second function depends on the policy argument as follows (if more than one of these conditions applies, the implementation may choose any of the corresponding policies).
因此 async(...) == async(launch::async
[解决办法]
launch::deferred, ...);
并且实现可以自由选择 async 方式,或 deferred 方式。
该段同时定义了两种方式的行为,见下。
if policy & launch::async is non-zero, calls INVOKE(DECAY_COPY (std::forward<F>(f)), DECAY_COPY (std::forward<Args>(args))...) (20.8.2, 30.3.1.2) as if in a new thread of execution represented by a thread object with the calls to DECAY_COPY () being evaluated in the thread that called async.
同时
if policy & launch::deferred is non-zero, ..., The first call to a non-timed waiting function
(30.6.4) on an asynchronous return object referring to this shared state shall invoke the deferred function in the thread that called the waiting function.
所以,g++ 选择同一线程以及其它实现选择多线程都符合标准,实际上 30.6.8/9 特地说明了这个问题。
要想确保多线程执行,用户必须自己说清楚。
[解决办法]
mingw4.8.0 ( 不使用std::launch::async )
0: 1
1: 1
2: 1
3: 1
4: 1
5: 1
6: 1
7: 1
8: 1
9: 1
mingw4.8.0 (使用std::launch::async)
5: 7
3: 5
7: 9
1: 3
9: 11
2: 4
0: 2
4: 6
6: 8
8: 10
我稍微改了一下代码,把i值传入线程里了。冒号前面为i值,后面为ThreadId。
[解决办法]
我觉得这版的多线程支持设计的确是不太好,比如 thread 需要自己 join 或 detach,要是忘记了,析构函数也不管,直接死程序,不知道委员会怎么想的。