You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何等待互斥锁解锁且不后续锁定?反向条件变量技术问询

解决方案:使用std::shared_mutex实现多读单写同步

你的需求正好匹配读写锁的场景,C++17及以后的标准库提供了std::shared_mutex,结合std::shared_lock和std::unique_lock就能完美解决问题:

  • 读取线程(包括std::for_each(par_unseq)启动的所有子线程)使用std::shared_lock<std::shared_mutex>获取共享锁:多个读取线程可以同时持有共享锁,互相不阻塞,完全满足无写入时并行读取的需求。
  • 主线程写入时使用std::unique_lock<std::shared_mutex>获取独占锁:此时所有尝试获取共享锁的读取线程会被阻塞(操作系统层面挂起线程,不会忙循环),直到主线程释放独占锁后,读取线程才能继续执行。

代码示例

#include <shared_mutex>
#include <execution>
#include <algorithm>
#include <vector>

std::shared_mutex data_mutex;
std::vector<int> shared_data; // 共享数据

// 子线程的读取+计算逻辑
void process_data() {
    std::for_each(std::execution::par_unseq, shared_data.begin(), shared_data.end(), [&](int& elem) {
        // 获取共享锁,读取数据
        std::shared_lock lock(data_mutex);
        int value = elem;
        // 如果计算不需要实时访问数据,可以提前释放锁,提升并行效率
        lock.unlock();
        
        // 执行大量计算
        // ...
    });
}

// 主线程的写入逻辑
void write_data(int new_value) {
    // 获取独占锁,阻塞所有读取线程
    std::unique_lock lock(data_mutex);
    // 执行写入操作
    shared_data.push_back(new_value);
    // 锁会在作用域结束时自动释放,读取线程恢复执行
}

关键优势

  1. 无需预知线程数:不管std::for_each启动多少个线程,每个线程只需独立获取共享锁即可,不需要提前协调数量。
  2. 无额外等待开销:没有写入操作时,读取线程完全并行,不会因为同步机制产生额外等待。
  3. 操作系统级阻塞:标准库的锁机制会通过操作系统调度挂起等待的线程,避免忙循环带来的CPU资源浪费。

注意事项

  • 如果你的计算过程需要确保共享数据不被修改(比如计算依赖数据的连续状态),不要提前释放共享锁,让锁持有到计算完成即可。
  • std::execution::par_unseq允许编译器进行更激进的优化,确保锁的操作是线程安全的,不要在迭代逻辑中出现锁的嵌套或不当释放。

内容的提问来源于stack exchange,提问作者Smasheded

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:00:03