大纲 C++ 并发编程 扩展阅读 - [C++ 多线程编程之一](/posts/a2a7ad9b.html)
条件变量 条件变量的概述 std::condition_variable 是 C++ 标准库中用于线程间同步的一个核心工具,它允许线程之间通过事件通知机制进行协作。
核心作用:
(1) 阻塞线程:让一个或多个线程在特定条件不满足时进入等待(休眠)状态,从而避免无意义的忙等(Busy-Waiting),释放 CPU 资源。 (2) 唤醒线程:允许另一个线程在修改共享数据后,通知(唤醒)那些正在等待的线程,让它们重新检查条件并继续执行。 核心函数:
等待函数(阻塞)wait(unique_lock<mutex>& lock):原子性地解锁传入的互斥量并使当前线程进入阻塞状态,直到被 notify 唤醒。被唤醒后,它会重新获取互斥量(加锁)并继续执行(通常需要配合循环检查条件)。wait(unique_lock<mutex>& lock, Predicate pred):带谓词(条件检查)的重载。等效于 while (!pred()) wait(lock),它会自动处理虚假唤醒,只有在条件满足时才真正返回。 通知函数(唤醒)notify_one():唤醒正在等待队列中的任意一个线程(如果有的话)。如果多个线程在等待,系统调度选择一个唤醒。notify_all():唤醒所有正在等待的线程。这些线程会竞争互斥量,并依次检查各自的条件。 带超时的等待函数wait_for() 和 wait_until():允许线程等待一段特定时间或等待到某个绝对时间点。如果超时后仍未收到通知,线程会自动醒来继续执行,避免永久阻塞。 特别注意 - `std::condition_variable` 必须与 `std::unique_lock`配合使用(不能使用`std::lock_guard`替代),因为等待期间需要原子性地释放锁。-`std::condition_variable`必须使用`while` 循环或谓词检查,因为存在虚假唤醒(Spurious Wakeup),即线程可能在未被通知的情况下醒来,必须重新验证条件是否真正满足。
条件变量的使用 !!! note 案例背景说明 在网络游戏服务器的设计中,共享数据的保护是一个典型案例:可以创建两个线程,其中一个线程负责收集玩家的命令并将命令数据写入队列,另一个线程则从队列中取出玩家发来的命令,进行解析并执行玩家所需的动作。值得一提的是,在当前业务场景下建议使用生产者消费者模型来实现,并使用 list 容器作为队列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 #include <atomic> #include <condition_variable> #include <iostream> #include <list> #include <mutex> #include <thread> using namespace std;class MyClass {public : void inMsgRecvQueue () { for (int i = 0 ; i < 1000 ; ++i) { std::unique_lock<std::mutex> lock (msgRecvQueueMutex) ; msgRecvQueue.push_back (i); lock.unlock (); condtion.notify_one (); std::this_thread::sleep_for (std::chrono::milliseconds (1 )); } std::unique_lock<std::mutex> lock (msgRecvQueueMutex) ; stop = true ; lock.unlock (); condtion.notify_all (); } void outMsgRecvQueue () { while (true ) { int command = -1 ; std::unique_lock<std::mutex> lock (msgRecvQueueMutex) ; condtion.wait (lock, [this ]() { return stop || !msgRecvQueue.empty (); }); if (stop && msgRecvQueue.empty ()) { break ; } if (!msgRecvQueue.empty ()) { command = msgRecvQueue.front (); msgRecvQueue.pop_front (); } lock.unlock (); if (command != -1 ) { std::cout << "已处理玩家命令: " << command << std::endl; } std::this_thread::sleep_for (std::chrono::milliseconds (1 )); } } private : bool stop = false ; std::list<int > msgRecvQueue; std::mutex msgRecvQueueMutex; std::condition_variable condtion; }; int main () { std::cout << "main thread start." << std::endl; MyClass mc; std::thread t_write (&MyClass::inMsgRecvQueue, &mc) ; std::thread t_read (&MyClass::outMsgRecvQueue, &mc) ; t_write.join (); t_read.join (); std::cout << "main thread end." << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 7 已处理玩家命令: 0 已处理玩家命令: 1 已处理玩家命令: 2 ...... 已处理玩家命令: 997 已处理玩家命令: 998 已处理玩家命令: 999
std::async std::async 的概述概述:
std::async 是 C++ 11 引入的异步任务启动机制,用于将函数异步执行,并返回一个 std::future 对象,以便获取任务执行结果或等待任务完成。特点:
简化多线程编程 :无需手动创建和管理 std::thread。线程同步调用 :调用 get() 时,如果任务尚未完成,会阻塞当前线程等待执行结果。异步结果获取 :支持通过 std::future 从异步任务中获取返回结果。一次性读取结果 :std::future 的结果只能通过 get() 获取一次,获取后对象将失效。支持异常传播 :任务中抛出的异常会保存在 std::future 中,在调用 get() 时重新抛出异常。自动资源管理 :任务结束后线程资源自动回收,无需 join() 或 detach()。支持状态查询 :可以通过 wait_for()、wait_until() 判断任务是否完成。启动策略:
std::async 支持三种启动方式:启动策略 说明 std::launch::async立即创建新线程执行任务。 std::launch::deferred延迟执行,直到调用 get() 或 wait() 时才在当前线程(不会创建子线程) 执行。 默认策略 由实现决定采用立即执行还是延迟执行。
常用成员函数:
get():获取任务返回值(只能调用一次)。wait():等待任务完成。wait_for():等待指定时间。wait_until():等待直到指定时间点。优点:
使用简单,代码量少。 自动管理线程生命周期。 支持返回值和异常传递。 适合执行独立的异步计算任务。 缺点:
默认启动策略具有不确定性,可能不会真正创建线程。 无法直接控制线程属性(如线程名称、优先级等)。 大量创建异步任务可能带来线程创建开销,不适合高并发场景。 适用场景:
后台计算任务。 并行执行多个独立任务。 需要获取任务返回值的异步操作。 临时性的异步任务,而非长期运行的线程。 !!! note 总结std::async 是 C++ 11 提供的高级异步任务接口,它可以自动创建并管理线程,返回 std::future 用于获取执行结果,是比 std::thread 更易用的异步编程方式。
std::async 的使用使用案例一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <chrono> #include <future> #include <iostream> #include <thread> int process (int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; return 5 ; } int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::future<int > result = std::async (process, 5000 ); std::cout << "continue ..." << std::endl; const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 main() run, thread id 1 continue ... process() start, current thread id 2 process() end, current thread id 2 result = 5 main() end, thread id 1
特别注意
在上面的 std::async 案例代码中,即使不手动调用 std::future 的 get() 函数,main 线程也会等待子线程执行完成。
使用案例二 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <chrono> #include <future> #include <iostream> #include <thread> class MyClass {public : int process (const int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; return 5 ; } }; int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; MyClass mc; std::future<int > result = std::async (&MyClass::process, &mc, 5000 ); std::cout << "continue ..." << std::endl; const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 main() run, thread id 1 continue ... process() start, current thread id 2 process() end, current thread id 2 result = 5 main() end, thread id 1
特别注意
在上面的 std::async 案例代码中,即使不手动调用 std::future 的 get() 函数,main 线程也会等待子线程执行完成。
使用案例三 std::async + std::launch::deferred 的使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <chrono> #include <future> #include <iostream> #include <thread> class MyClass {public : int process (const int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; return 5 ; } }; int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; MyClass mc; std::future<int > result = std::async (std::launch::deferred, &MyClass::process, &mc, 5000 ); std::cout << "continue ..." << std::endl; const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 main() run, thread id 1 continue ... process() start, current thread id 1 process() end, current thread id 1 result = 5 main() end, thread id 1
使用案例四 std::async + std::launch::async 的使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <chrono> #include <future> #include <iostream> #include <thread> class MyClass {public : int process (const int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; return 5 ; } }; int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; MyClass mc; std::future<int > result = std::async (std::launch::async, &MyClass::process, &mc, 5000 ); std::cout << "continue ..." << std::endl; const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 main() run, thread id 1 continue ... process() start, current thread id 2 process() end, current thread id 2 result = 5 main() end, thread id 1
std::packaged_task std::packaged_task 的概述 概述:
std::packaged_task 是 C++ 11 引入的异步任务封装机制,用于将一个可调用对象(普通函数、函数对象、Lambda 表达式等)封装成任务,并将任务执行结果与 std::future 关联起来,以便后续获取返回值或异常信息。特点:
任务封装管理 :可以将任意可调用对象包装成一个可执行任务,统一管理任务执行过程。结果异步获取 :任务执行完成后的返回值会保存到共享状态中,并通过关联的 std::future 获取。执行与获取分离 :任务的创建、执行和结果获取可以独立进行,提高任务调度灵活性。支持异常传播 :任务执行过程中抛出的异常会被保存起来,并在调用 future::get() 时重新抛出。一次执行机制 :一个 std::packaged_task 对象通常只能执行一次,执行完成后任务状态失效。支持移动语义 :std::packaged_task 不支持拷贝,只支持移动,适合在线程池、任务队列中传递。无需手动同步结果 :内部自动管理任务结果与 std::future 之间的关联。常用成员函数:
get_future():获取与任务结果关联的 std::future 对象,通常应该在任务执行前调用 。operator():执行封装的任务。valid():判断当前 std::packaged_task 是否有效。reset():重新绑定共享状态,使任务可以再次执行。与其他异步组件的关系:
组件 作用 std::future获取异步任务执行结果。 std::async自动启动异步任务,并返回 std::future。 std::packaged_task封装任务,将任务执行和结果获取分离。 std::promise手动设置异步结果,通常由一个线程生产结果,另一个线程通过 std::future 获取。
优点:
任务封装和线程管理分离,灵活性更高。 支持在线程池、任务队列中实现任务调度。 自动处理返回值和异常传递。 相比 std::async,可以更精细地控制任务执行方式。 缺点:
使用复杂度高于 std::async。 需要手动安排任务执行线程,不会自动创建线程 。一个任务对象只能执行一次,需要重新执行时必须调用 reset()。 适用场景:
线程池任务封装。 任务队列异步执行。 需要将任务提交和任务执行分离的场景。 多线程环境下需要统一管理异步任务结果的场景。 总结
std::packaged_task 是 C++ 11 提供的任务封装工具,它将可调用对象、任务执行和结果获取 进行解耦,通过 std::future 获取执行结果。相比 std::async,它提供了更灵活的任务调度能力,常用于线程池等高级异步编程场景。
特别注意
std::packaged_task 的 get_future() 通常应在任务执行前调用,以获取与任务结果关联的 std::future 对象。虽然部分编译器实现(例如 Windows 下的 MSVC)允许在任务执行完成后再调用 get_future(),代码也可能正常运行,但这并不是推荐的使用方式。为了保证代码的跨平台兼容性,并符合异步任务的设计思想,应在执行 packaged_task 前完成 std::future 获取,然后通过 future::get() 获取任务执行结果。
std::packaged_task 的使用 使用案例一 std::packaged_task + 普通函数的使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <chrono> #include <future> #include <iostream> #include <thread> int process (const int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; return 5 ; } int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::packaged_task<int (int ) > task (process) ; std::future<int > result = task.get_future (); std::thread t1 (std::ref(task), 5000 ) ; t1.join (); const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 main() run, thread id 1 process() start, current thread id 2 process() end, current thread id 2 result = 5 main() end, thread id 1
使用案例二 std::packaged_task + Lambda 表达式的使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <chrono> #include <future> #include <iostream> #include <thread> int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::packaged_task<int (int ) > task ([](const int milliseconds) -> int { std::cout << "process start, current thread id " << std::this_thread::get_id() << std::endl; const std::chrono::milliseconds ms(milliseconds); std::this_thread::sleep_for(ms); std::cout << "process end, current thread id " << std::this_thread::get_id() << std::endl; return 5 ; }) ; std::future<int > result = task.get_future (); std::thread t1 (std::ref(task), 5000 ) ; t1.join (); const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 main() run, thread id 1 process start, current thread id 2 process end, current thread id 2 result = 5 main() end, thread id 1
使用案例三 std::packaged_task 作为可调用对象直接调用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <chrono> #include <future> #include <iostream> #include <thread> int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::packaged_task<int (int ) > task ([](const int milliseconds) -> int { std::cout << "process start, current thread id " << std::this_thread::get_id() << std::endl; const std::chrono::milliseconds ms(milliseconds); std::this_thread::sleep_for(ms); std::cout << "process end, current thread id " << std::this_thread::get_id() << std::endl; return 5 ; }) ; std::future<int > result = task.get_future (); task (5000 ); const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 main() run, thread id 1 process start, current thread id 1 process end, current thread id 1 result = 5 main() end, thread id 1
使用案例四 std::packaged_task + std::vector 容器的使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <chrono> #include <future> #include <iostream> #include <thread> #include <vector> int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::packaged_task<int (int ) > task ([](const int milliseconds) -> int { std::cout << "process start, current thread id " << std::this_thread::get_id() << std::endl; const std::chrono::milliseconds ms(milliseconds); std::this_thread::sleep_for(ms); std::cout << "process end, current thread id " << std::this_thread::get_id() << std::endl; return 5 ; }) ; std::vector<std::packaged_task<int (int )>> tasks; tasks.push_back (std::move (task)); const auto iter = tasks.begin (); std::packaged_task<int (int )> task2 = std::move (*iter); tasks.erase (iter); std::future<int > result = task2.get_future (); task2 (5000 ); const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 main() run, thread id 1 process start, current thread id 1 process end, current thread id 1 result = 5 main() end, thread id 1
使用案例五 std::packaged_task + std::queue 实现任务队列(常用于线程池)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 #include <chrono> #include <future> #include <iostream> #include <mutex> #include <queue> #include <thread> int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::queue<std::packaged_task<int (int )>> tasks; std::mutex mutex; std::packaged_task<int (int ) > task ([](const int milliseconds) -> int { std::cout << "process start, current thread id " << std::this_thread::get_id() << std::endl; const std::chrono::milliseconds ms(milliseconds); std::this_thread::sleep_for(ms); std::cout << "process end, current thread id " << std::this_thread::get_id() << std::endl; return 5 ; }) ; std::future<int > result = task.get_future (); { std::lock_guard<std::mutex> lock (mutex) ; tasks.push (std::move (task)); } std::thread worker ([&tasks, &mutex]() { std::cout << "worker thread start, thread id " << std::this_thread::get_id() << std::endl; std::packaged_task<int (int )> current_task; { std::lock_guard<std::mutex> lock(mutex); if (!tasks.empty()) { current_task = std::move(tasks.front()); tasks.pop(); } } if (current_task.valid()) { current_task(5000 ); } std::cout << "worker thread end, thread id " << std::this_thread::get_id() << std::endl; }) ; worker.join (); const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 7 main() run, thread id 1 worker thread start, thread id 2 process start, current thread id 2 process end, current thread id 2 worker thread end, thread id 2 result = 5 main() end, thread id 1
std::promise std::promise 的概述概述:
std::promise 是 C++ 11 引入的异步结果传递机制,用于在线程之间传递数据或异常 。它与 std::future 配合使用,一个线程通过 std::promise 设置结果,另一个线程通过关联的 std::future 获取结果。特点:
线程间数据传递 :支持一个线程向另一个线程传递异步执行结果。主动设置结果 :与 std::async 和 std::packaged_task 自动保存结果不同,std::promise 需要开发者手动调用接口设置结果。支持异常传递 :可以在线程中保存异常信息,并通过 future::get() 在另一线程重新抛出异常。一次性赋值 :一个 std::promise 对象只能设置一次结果,重复设置会产生异常。与 std::future 配合使用 :通过 get_future() 获取关联的 std::future 对象,实现结果同步。支持移动语义 :std::promise 不支持拷贝,只支持移动,适合在线程间转移所有权。常用成员函数:
get_future():获取与当前 promise 关联的 std::future 对象。set_value():设置异步任务的返回结果。set_exception():设置异常结果,并传递给等待获取结果的线程。swap():交换两个 std::promise 对象的状态。与其他异步组件的关系:
组件 作用 std::future获取异步操作的结果。 std::promise手动设置异步操作的结果或异常。 std::packaged_task封装任务,并自动将执行结果保存到 std::future。 std::async自动启动异步任务,并返回 std::future。
优点:
提供灵活的线程间通信方式。 可以精确控制结果产生的时机。 支持结果和异常统一传递。 适合实现自定义异步任务模型。 缺点:
需要手动管理任务执行和结果设置。 使用复杂度高于 std::async。 一个 promise 只能关联一个 future,不适合一对多结果通知场景。 适用场景:
多线程之间传递计算结果。 线程任务完成通知。 自定义异步任务框架。 线程池中任务执行结果返回。 需要手动控制异步结果产生时机的场景。 总结
std::promise 是 C++ 11 提供的底层异步通信工具,它负责生产异步结果 ,而 std::future 负责获取异步结果 。相比 std::async 和 std::packaged_task,std::promise 提供了更灵活的结果控制能力,常用于线程间通信和自定义异步任务实现。
std::promise 的使用使用案例一 std::promise + std::future 的简单使用1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <chrono> #include <future> #include <iostream> #include <thread> void process (std::promise<int >& result, int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; result.set_value (5 ); } int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::promise<int > mpro; std::future<int > result = mpro.get_future (); std::thread t1 (process, std::ref(mpro), 5000 ) ; t1.join (); const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 main() run, thread id 1 process() start, current thread id 2 process() end, current thread id 2 result = 5 main() end, thread id 1
使用案例二 std::promise + std::future 在不同线程间通信的典型使用方式process() 线程负责生产结果,通过 promise.set_value() 设置数据结果;process2() 线程负责消费结果,通过 future.get() 等待并获取数据结果。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <chrono> #include <future> #include <iostream> #include <thread> void process (std::promise<int >& result, int milliseconds) { std::cout << "process() start, current thread id " << std::this_thread::get_id () << std::endl; const std::chrono::milliseconds ms (milliseconds) ; std::this_thread::sleep_for (ms); std::cout << "process() end, current thread id " << std::this_thread::get_id () << std::endl; result.set_value (5 ); } void process2 (std::future<int > result) { std::cout << "process2() start, current thread id " << std::this_thread::get_id () << std::endl; const int num = result.get (); std::cout << "result = " << num << std::endl; std::cout << "process2() end, current thread id " << std::this_thread::get_id () << std::endl; } int main () { std::cout << "main() run, thread id " << std::this_thread::get_id () << std::endl; std::promise<int > mpro; std::future<int > result = mpro.get_future (); std::thread t1 (process, std::ref(mpro), 5000 ) ; std::thread t2 (process2, std::move(result)) ; t1.join (); t2.join (); std::cout << "main() end, thread id " << std::this_thread::get_id () << std::endl; return 0 ; }
程序运行的结果如下:
1 2 3 4 5 6 7 main() run, thread id 1 process2() start, current thread id 3 process() start, current thread id 2 process() end, current thread id 2 result = 5 process2() end, current thread id 3 main() end, thread id 1