std::notify_all_at_thread_exit
来自cppreference.com
在标头 <condition_variable> 定义
|
||
void notify_all_at_thread_exit( std::condition_variable& cond, std::unique_lock<std::mutex> lk ); |
(C++11 起) | |
notify_all_at_thread_exit
提供一种机制,通知其他线程给定的线程已完全完成,包括销毁所有 thread_local 对象。它操作如下:
- 将先前获得的锁 lk 的所有权转移到内部存储。
- 修改执行环境,以令当前线程退出时,如同以 lk.unlock();
cond.notify_all(); 通知条件变量 cond。
隐含的 lk.unlock 按顺序晚于与当前线程关联的所有拥有线程局域存储期的对象析构。
如果满足以下任意条件,那么行为未定义:
- 调用线程没有锁定 lk。
- 在有其他线程也在 cond 上等待的情况下,那些线程在 cond 上调用的等待函数(
wait
、wait_for 以及 wait_until)解锁的互斥与 lk.mutex() 不同。
注解
等价的效果可以用 std::promise 或 std::packaged_task 所提供的设施达成。
保有提供的锁 lk 直至线程退出。一旦调用此函数,则不会再有线程可获得相同的锁以在 cond 上等待。若某些线程正在此条件变量上等待,则应确保所等待的条件是在持有 lk 的锁时满足的,并且在调用 notify_all_at_thread_exit
之前不应释放和重获得锁,以避免其他线程中发生虚假唤醒的混乱。
典型使用情况中,此函数是被脱附线程所做的最后行动。
参数
cond | - | 在线程退出时通知的条件变量 |
lk | - | 与条件变量 cond 关联的锁 |
返回值
(无)
示例
此部分代码零碎地描绘 notify_all_at_thread_exit
能如何用于避免在线程局域对象处于被析构过程时,访问依赖于它们的数据:
运行此代码
#include <cassert> #include <condition_variable> #include <mutex> #include <string> #include <thread> std::mutex m; std::condition_variable cv; bool ready = false; ComplexType result; // 某种任意类型 void thread_func() { thread_local std::string thread_local_data = "42"; std::unique_lock<std::mutex> lk(m); // 用 thread_local 数据赋值给 result result = thread_local_data; ready = true; std::notify_all_at_thread_exit(cv, std::move(lk)); } // 1. 销毁 thread_local 对象; // 2. 解锁互斥体; // 3. 通知 cv。 int main() { std::thread t(thread_func); t.detach(); // 做其他工作 // .… // 等待脱附的线程 std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{ return ready; }); // result 已就绪且 thread_local 析构函数已完成,无 UB assert(result == "42"); }
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 2140 | C++11 | notify_all_at_thread_exit 的调用同步于在 cond 上等待的函数的调用
|
更新同步要求 |
参阅
设置结果为指定值,同时仅在线程退出时分发提醒 ( std::promise<R> 的公开成员函数) | |
执行函数,并确保结果仅在一旦当前线程退出时就绪 ( std::packaged_task<R(Args...)> 的公开成员函数) |