std::async 块甚至带有 std::launch::async 标志取决于是使用还是忽略返回的 future
std::async blocks even with std::launch::async flag depending on whether the returned future is used or ignored
问题描述
std::async
似乎即使使用 std::launch::async
标志也会阻塞:
#include <iostream>
#include <future>
#include <chrono>
int main(void)
{
using namespace std::chrono_literals;
auto f = [](const char* s)
{
std::cout << s;
std::this_thread::sleep_for(2s);
std::cout << s;
};
std::cout << "start\n";
(void)std::async(std::launch::async, f, "1\n");
std::cout << "in between\n";
(void)std::async(std::launch::async, f, "2\n");
std::cout << "end\n";
return 0;
}
输出显示执行已序列化。即使有 std::launch::async
标志。
start
1
1
in between
2
2
end
但是如果我使用返回的std::future
,它突然开始不阻塞了!
我所做的唯一更改是删除 (void)
并改为添加 auto r1 =
:
#include <iostream>
#include <future>
#include <chrono>
int main(void)
{
using namespace std::chrono_literals;
auto f = [](const char* s)
{
std::cout << s;
std::this_thread::sleep_for(2s);
std::cout << s;
};
std::cout << "start\n";
auto r1 = std::async(std::launch::async, f, "1\n");
std::cout << "in between\n";
auto r2 = std::async(std::launch::async, f, "2\n");
std::cout << "end\n";
return 0;
}
而且,结果大不相同。它肯定表明执行是并行的。
start
in between
1
end
2
1
2
我为 CentOS devtoolset-7 使用了 gcc。
gcc (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我的Makefile
是:
.PHONY: all clean
all: foo
SRCS := $(shell find . -name '*.cpp')
OBJS := $(SRCS:.cpp=.o)
foo: $(OBJS)
gcc -o $@ $^ -lstdc++ -pthread
%.o: %.cpp
gcc -std=c++17 -c -g -Wall -O0 -pthread -o $@ $<
clean:
rm -rf foo *.o
问题
规范中是否有此行为?
还是gcc实现的bug?
为什么会这样?
有人可以给我解释一下吗?
std::future
析构函数将 block if it’s a future from std::async
and is the last reference to the shared state。我相信你在这里看到的是
- 对
async
return 的调用是 future
,但是
future
没有被捕获,所以
future
的析构函数触发,
- 块,导致任务以串行方式完成。
显式捕获 return 值会导致两个析构函数仅在函数结束时触发,这会使两个任务 运行 直到完成。
问题描述
std::async
似乎即使使用 std::launch::async
标志也会阻塞:
#include <iostream>
#include <future>
#include <chrono>
int main(void)
{
using namespace std::chrono_literals;
auto f = [](const char* s)
{
std::cout << s;
std::this_thread::sleep_for(2s);
std::cout << s;
};
std::cout << "start\n";
(void)std::async(std::launch::async, f, "1\n");
std::cout << "in between\n";
(void)std::async(std::launch::async, f, "2\n");
std::cout << "end\n";
return 0;
}
输出显示执行已序列化。即使有 std::launch::async
标志。
start
1
1
in between
2
2
end
但是如果我使用返回的std::future
,它突然开始不阻塞了!
我所做的唯一更改是删除 (void)
并改为添加 auto r1 =
:
#include <iostream>
#include <future>
#include <chrono>
int main(void)
{
using namespace std::chrono_literals;
auto f = [](const char* s)
{
std::cout << s;
std::this_thread::sleep_for(2s);
std::cout << s;
};
std::cout << "start\n";
auto r1 = std::async(std::launch::async, f, "1\n");
std::cout << "in between\n";
auto r2 = std::async(std::launch::async, f, "2\n");
std::cout << "end\n";
return 0;
}
而且,结果大不相同。它肯定表明执行是并行的。
start
in between
1
end
2
1
2
我为 CentOS devtoolset-7 使用了 gcc。
gcc (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1)
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我的Makefile
是:
.PHONY: all clean
all: foo
SRCS := $(shell find . -name '*.cpp')
OBJS := $(SRCS:.cpp=.o)
foo: $(OBJS)
gcc -o $@ $^ -lstdc++ -pthread
%.o: %.cpp
gcc -std=c++17 -c -g -Wall -O0 -pthread -o $@ $<
clean:
rm -rf foo *.o
问题
规范中是否有此行为?
还是gcc实现的bug?
为什么会这样?
有人可以给我解释一下吗?
std::future
析构函数将 block if it’s a future from std::async
and is the last reference to the shared state。我相信你在这里看到的是
- 对
async
return 的调用是future
,但是 future
没有被捕获,所以future
的析构函数触发,- 块,导致任务以串行方式完成。
显式捕获 return 值会导致两个析构函数仅在函数结束时触发,这会使两个任务 运行 直到完成。