std::notify_all_at_thread_exit
来自cppreference.com
<tbody>
</tbody>
| 在标头 <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...)> 的公开成员函数)
|