C++-std::async与std::future基本使用
- std::launch::deferred表明任务将在future::get或者future::wait时执行(同一线程)
- std::launch::async表明任务必须在新线程执行
launch::deferred
int add(int a, int b)
{cout << "work thread" << this_thread::get_id() << endl;Sleep(3000);return a + b;
}int main()
{cout << "main thread" << this_thread::get_id() << endl;future<int> result = async(launch::deferred, add, 2, 3);//1Sleep(3000);cout << result.get() << endl;
}
0s: main 函数启动,输出主线程 ID
0s: 调用 async(launch::deferred, add, 2, 3),但 add 函数不会立即执行
0s: 主线程调用 Sleep(3000),进入休眠状态
3s: 主线程休眠结束,执行 result.get()
3s: 此时 add 函数开始执行,输出工作线程 ID(实际上和主线程 ID 相同)
3s: add 函数内部调用 Sleep(3000),主线程被阻塞
6s: add 函数执行完毕,返回 5
6s: result.get() 返回结果,主线程继续执行后续代码
async 启动策略:你采用了 launch::deferred 策略,这意味着 add 函数不会马上执行,而是会延迟到有代码调用 result.get() 或者 result.wait() 时才执行。
Sleep(3000) 的影响:在主线程里调用 Sleep(3000) 时,add 函数并不会运行,因为它处于延迟执行状态。
get() 的作用:当执行 result.get() 时,add 函数才开始执行。add 函数内部又有 Sleep(3000),这会让当前线程(也就是主线程)暂停 3 秒钟,直到 add 函数执行完毕。
总结:尽管代码中有两次 Sleep(3000),但 result.get() 依旧会阻塞主线程,因为 launch::deferred 策略使得 add 函数的执行被推迟到调用 get() 的时候。
launch::async
int add(int a, int b)
{cout << "work thread" << this_thread::get_id() << endl;Sleep(3000);return a + b;
}int main()
{cout << "main thread" << this_thread::get_id() << endl;// 把启动策略改为 launch::asyncfuture<int> result = async(launch::async, add, 2, 3);// 主线程可以在 add 函数执行期间继续执行其他任务Sleep(3000);// 此时 add 函数可能已经执行完毕,也可能还在执行cout << result.get() << endl; // 最多等待 add 函数剩余的执行时间
}
0s: main 函数启动,输出主线程 ID
0s: 调用 async(launch::async, add, 2, 3),add 函数在新线程开始执行
0s: 新线程输出工作线程 ID,然后调用 Sleep(3000)
0s: 主线程继续执行,调用 Sleep(3000)
3s: 主线程休眠结束,执行 result.get()
3s: 此时 add 函数可能已经执行完毕(如果工作线程的调度顺利)
3s: 如果 add 函数还没执行完,主线程最多等待 0 秒(因为工作线程的 Sleep 在 3s 时结束)
3s: result.get() 返回结果 5
启动策略调整:launch::async 会让 add 函数在新线程立即启动,不会出现延迟执行的情况。
执行流程变化:
主线程调用 async 后,add 函数会在后台线程开始执行。
主线程能够继续执行后续的 Sleep(3000) 操作,不会被阻塞。
当调用 result.get() 时,如果 add 函数已经执行完,就会立刻返回结果;如果还没执行完,最多等待剩余的执行时间。
ref
https://blog.csdn.net/mrbone11/article/details/121720602