命名空间
变体
操作

std::notify_all_at_thread_exit

来自 cppreference.cn
< cpp‎ | thread
 
 
并发支持库
线程
(C++11)
(C++20)
this_thread 命名空间
(C++11)
(C++11)
(C++11)
协同取消
互斥
(C++11)
通用锁管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
条件变量
notify_all_at_thread_exit
(C++11)
(C++11)
信号量
门闩和屏障
(C++20)
(C++20)
期值
(C++11)
(C++11)
(C++11)
(C++11)
安全回收
(C++26)
危险指针
原子类型
(C++11)
(C++20)
原子类型的初始化
(C++11)(C++20 中已弃用)
(C++11)(C++20 中已弃用)
内存排序
(C++11)(C++26 中已弃用)
原子操作的自由函数
原子标志的自由函数
 
在头文件 <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() 与这些线程在 cond 上调用的等待函数(waitwait_forwait_until)解锁的互斥量不同。

目录

[编辑] 注意

可以通过 std::promisestd::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++ 标准。

缺陷报告 应用于 发布时的行为 正确的行为
LWG 2140 C++11 调用 notify_all_at_thread_exit
与等待 cond 的函数的调用同步
更新了同步
要求

[编辑] 参阅

将结果设置为特定值,仅在线程退出时发送通知
(std::promise<R> 的公共成员函数) [编辑]
执行函数,确保仅在当前线程退出后结果才就绪
(std::packaged_task<R(Args...)> 的公共成员函数) [编辑]