6

std::async用来创建一个线程,我希望这个新线程应该单独执行,主线程不应该等待它。但是在这里,当我调用 std::async 时,会创建一个新线程,但主线程正在等待fun(). 我希望主线程在不等待fun()完成的情况下并行执行。我该怎么做?

#include <iostream>
#include <windows.h>
#include <future>
using namespace std;



void printid()
{
   cout << "Thread id is:" << this_thread::get_id() << endl;
}

void fun(void *obj)
{

   cout<<"Entry"<<endl;
   printid();
   Sleep(10000);
   cout<<"Exit"<<endl;
}


int main()
{
    cout<<"Hello"<<endl;
    printid();
    std::async(std::launch::async, fun, nullptr);
    cout << "After call" << endl;
}

我得到输出:

Hello
Thread id is:22832
Entry
Thread id is:13156
Exit
After call
4

3 回答 3

6

std::future由策略返回std::async并使用策略启动的对象std::launch::async在销毁时阻塞,直到启动的任务完成。

由于您没有将返回std::future的值存储在变量中,因此它在语句末尾被销毁,因此std::asyncmain任务完成之前无法继续。

如果你存储std::future对象,它的生命周期将延长到最后,main你会得到你想要的行为。

int main()
{
    ...
    auto fut = std::async(std::launch::async, fun, nullptr);
    ...
}
于 2018-02-02T04:14:12.287 回答
3
std::async(std::launch::async, fun, nullptr);

对返回的 不做任何事情std::future,让它被销毁。这是一个问题,因为std::future' 的析构函数可能会阻塞并等待线程完成。

解决方案是坚持std::future一段时间,然后在完成其他所有操作后将其销毁。

auto locallyScopedVariable = std::async(std::launch::async, fun, nullptr);

locallyScopedVariable将在结束时超出范围,main然后阻塞直到完成。

请注意,这仍然可能无法达到您想要的效果。主线程可以立即将处理器让给新线程,并允许新线程在返回控制之前运行完成。可以更正代码,但仍会导致输出不正确的版本。

于 2018-02-02T04:09:48.567 回答
0

(1) 在多线程程序测试中,使用互斥锁保护共享资源(本例中为cout)不被不同线程同时调用。(2) 主要检查future是否准备好,你也可以做一个超时。

void print_id() 
{
    lock_guard<mutex> locker(mutex_);
    cout << "Thread id is:" << this_thread::get_id() << endl;
}

void print( string str) 
{
    lock_guard<mutex> locker(mutex_);
    cout << str << '\n';
}   

bool fun(void *obj)
{
   print("Entry");
   printid();
   Sleep(10000);
   print("Exit");
   return true;
}


int main()
{
    print("Hello");
    printid();
    std::future<bool> fut = std::async(std::launch::async, fun,nullptr);
    while(!fut->_Is_ready() )
    {
     }
    cout << "After call" << endl;
}
于 2018-02-02T10:04:51.287 回答