std::notify_all_at_thread_exit
来自 cppreference.cn
定义于头文件 <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 的所有权被转移到内部存储。
- 执行环境被修改,以便当当前线程退出时,条件变量 cond 会被通知,如同通过 lk.unlock();
cond.notify_all(); 一样。
隐含的 lk.unlock() 排序在后 于与当前线程关联的具有 线程局部存储期 的所有对象的销毁之后。
如果满足以下任何条件,则行为未定义:
- lk 未被调用线程锁定。
- 如果其他一些线程也在等待 cond,则 lk.mutex() 与等待函数(
wait
、wait_for 和 wait_until)在 cond 上调用的解锁互斥量不同。
内容 |
[编辑] 注解
使用 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; std::string result; // some arbitrary type void thread_func() { thread_local std::string thread_local_data = "42"; std::unique_lock<std::mutex> lk(m); // assign a value to result using thread_local data result = thread_local_data; ready = true; std::notify_all_at_thread_exit(cv, std::move(lk)); } // 1. destroy thread_locals; // 2. unlock mutex; // 3. notify cv. int main() { std::thread t(thread_func); t.detach(); // do other work // ... // wait for the detached thread std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{ return ready; }); // result is ready and thread_local destructors have finished, no UB assert(result == "42"); }
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
LWG 2140 | C++11 | 对 notify_all_at_thread_exit 的调用与对等待 cond 的函数的调用同步 |
更新了同步 要求 |
[编辑] 参见
设置结果为特定值,同时仅在线程退出时传递通知 ( std::promise<R> 的公共成员函数) | |
执行函数,确保仅在当前线程退出后结果才准备就绪 ( std::packaged_task<R(Args...)> 的公共成员函数) |