命名空间
变体
操作

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)
Hazard Pointers
原子类型
(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() 与等待函数(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...)> 的公共成员函数) [编辑]