为何C++标准库未提供类似timed_mutex的atomic::try_load_for与try_store_for?
我开发了一款需响应安全关键事件的程序,必须保证循环内的执行进度,因此要求循环内所有函数调用都带有超时机制,同时需要使用原子数据类型。std::atomic<my_struct>本可满足需求,但它并没有类似try_lock_for的函数。我自己实现了一个带超时的原子包装类(代码如下),想知道为何C++标准库至今未提供这类功能?
#ifndef TIMED_ATOMIC_HPP #define TIMED_ATOMIC_HPP #include <mutex> #include <chrono> #include <expected> #include <memory> #include <type_traits> template<typename T> struct is_shared_ptr : std::false_type {}; template <typename U> struct is_shared_ptr<std::shared_ptr<U>> : std::true_type {}; template <typename T> struct is_unique_ptr : std::false_type {}; template <typename U, typename D> struct is_unique_ptr<std::unique_ptr<U, D>> : std::true_type {}; template <typename T> struct is_raw_pointer : std::is_pointer<T> {}; template <typename T> concept NotPointerType = !is_raw_pointer<T>::value && !is_unique_ptr<T>::value && !is_shared_ptr<T>::value; template<typename T> concept AllowedType = NotPointerType<T> && std::is_copy_constructible_v<T> && std::is_move_constructible_v<T>; /// @brief Wrapper class to allow threadsafe access with a timeout. This is required because the robot state update thread should never hang because it is responsible for stopping the robot in case exit_flag is set. template<typename T> requires AllowedType<T> class timed_atomic { private: std::timed_mutex mtx {}; T value {}; public: explicit timed_atomic(T initial_value) : value{initial_value} {} timed_atomic() = default; std::expected<T, std::monostate> try_load_for(std::chrono::microseconds timeout_us) { std::unique_lock lock{mtx, std::defer_lock}; if(!lock.try_lock_for(timeout_us)) { return std::unexpected{std::monostate{}}; } return value; } bool try_store_for(T new_value, std::chrono::microseconds timeout_us) { std::unique_lock lock{mtx, std::defer_lock}; if(!lock.try_lock_for(timeout_us)) { return false; } value = std::move(new_value); return true; } }; #endif
我曾查找过类似timed_mutex的std::atomic::try_lock_for相关内容,找到了《C++20: How to wait on an atomic object with timeout?》,但其中的wait函数并非我所需。
补充说明:更多上下文可参考《"Real-time" multithreaded design with timeouts》,中文译名为《带有超时的“实时”多线程设计》
核心原因:原子类型与超时锁的设计目标本质冲突
std::atomic的设计初衷是利用硬件原子指令实现无锁、低延迟的内存同步,它的所有操作都是直接映射到CPU的原子指令(比如lock cmpxchg),全程不需要操作系统内核介入,保证了极致的性能和确定性。而try_lock_for这类超时机制是互斥锁的特性,依赖操作系统的线程调度来阻塞/唤醒线程,本质是一种阻塞式同步,和原子类型的“无锁、轻量”设计哲学完全相悖。
C++标准库刻意保持std::atomic的极简性,只暴露硬件原生支持的原子操作——如果把超时等待这类需要内核参与的逻辑塞进原子类型,会彻底改变它的定位,让它变成一个“披着原子外衣的互斥锁”,混淆了两种完全不同的同步模型。
关于C++20的atomic::wait
你提到的C++20原子wait函数,它的定位是替代忙等待的通知机制:当原子值未达到预期时,线程可以进入休眠,直到其他线程修改原子值并通知它。它并不提供对原子数据的独占访问锁定,因此确实不符合你需要的“带超时的读写控制”场景。
你的自定义实现是合理的选择
你实现的timed_atomic本质是用std::timed_mutex包装数据,提供带超时的线程安全读写,这在安全关键的实时场景下完全合理——它既保证了数据访问的线程安全,又能避免线程无限阻塞,符合你对循环执行进度的要求。标准库没有提供这类封装,是因为这类需求属于“特定场景下的同步封装”,标准库更倾向于提供基础组件(比如timed_mutex、atomic),让开发者根据需求组合实现,而不是覆盖所有细分场景。
内容的提问来源于Stack Exchange,提问作者Hans Müller

