命名空间
变体
操作

std::notify_all_at_thread_exit

来自 cppreference.com
< 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 中已弃用)
内存排序
原子操作的自由函数
原子标志的自由函数
 
定义在头文件 <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() 与等待函数(waitwait_forwait_until)在 cond 上解锁的互斥锁不同,这些函数由那些线程调用。

内容

[编辑] 注释

可以使用 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++ 标准。

DR 应用于 已发布的行为 正确行为
LWG 2140 C++11 notify_all_at_thread_exit 的调用
与在 cond 上等待的函数的调用同步
更新了同步
要求

[编辑] 另请参阅

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