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

C++11在Windows下共享访问极罕见时,如何最优锁定资源?

最优实现方案:Windows SRWLOCK 轻量级读写锁

针对你这种读操作(规则检查)占99.9%、写操作(规则增删)极少,且要求“增删规则时禁止检查操作执行”的场景,Windows原生的SRWLOCK(轻量级读写锁)是最匹配的选择,既能保证读操作的极致性能,又能在写操作期间完全阻塞读请求。

核心逻辑

  • 规则检查(读操作):使用共享锁,多个读线程可同时进入,无锁竞争时几乎没有性能开销;
  • 规则增删(写操作):使用独占锁,一旦获取锁,所有读操作会被阻塞,直到写操作完成并释放锁,彻底保证“增删时不执行检查”的要求;
  • SRWLOCK是用户态锁,仅在出现锁竞争时才会进入内核态,而你的写操作极少,几乎不会触发内核态切换,性能远超普通互斥锁。

代码实现示例

#include <windows.h>
#include <vector>
#include <algorithm>

// 假设你的规则类型定义如下
struct Rule {
    DWORD targetPid;
    bool allow;

    bool Match(DWORD pid) const {
        return targetPid == pid;
    }

    bool operator==(const Rule& other) const {
        return targetPid == other.targetPid && allow == other.allow;
    }
};

class RuleManager {
private:
    SRWLOCK m_srwLock = SRWLOCK_INIT;
    std::vector<Rule> m_rules;

public:
    // 规则检查:读操作,获取共享锁
    bool CheckPermission(DWORD pid) {
        AcquireSRWLockShared(&m_srwLock);
        
        bool result = false;
        for (const auto& rule : m_rules) {
            if (rule.Match(pid)) {
                result = rule.allow;
                break;
            }
        }
        
        ReleaseSRWLockShared(&m_srwLock);
        return result;
    }

    // 添加规则:写操作,获取独占锁
    void AddRule(const Rule& newRule) {
        AcquireSRWLockExclusive(&m_srwLock);
        m_rules.push_back(newRule);
        ReleaseSRWLockExclusive(&m_srwLock);
    }

    // 删除规则:写操作,获取独占锁
    void RemoveRule(const Rule& ruleToRemove) {
        AcquireSRWLockExclusive(&m_srwLock);
        auto it = std::find(m_rules.begin(), m_rules.end(), ruleToRemove);
        if (it != m_rules.end()) {
            m_rules.erase(it);
        }
        ReleaseSRWLockExclusive(&m_srwLock);
    }
};

为什么这个方案比你考虑的选项更好?

  • 比std::mutex性能高:std::mutex每次检查都需要加解锁,即使没有竞争也有开销;而SRWLOCK的共享锁在无写操作时是原子操作,几乎零开销;
  • 比Critical Sections更优:Windows 8.1+上Critical Sections的性能确实不如std::mutex,而SRWLOCK作为专门的读写锁,读密集场景下的性能远高于两者;
  • 完全满足业务要求:写操作时独占锁会阻塞所有读请求,确保增删规则期间没有检查操作执行,读操作时无额外负担,完美平衡安全与性能。

备选方案:双缓冲无锁发布(适合允许读旧数据的场景)

如果你的需求可以放宽为“增删规则时允许检查操作读取旧规则列表”,而非严格禁止检查执行,那么双缓冲无锁方案能实现极致的读性能:

  • 维护两个规则列表:一个活跃列表供读操作直接访问,一个备用列表供写操作修改;
  • 写操作时复制活跃列表到备用列表,修改后通过原子指针替换活跃列表;
  • 读操作无需任何锁,直接读取原子指针指向的列表。

简化代码示例:

#include <atomic>
#include <vector>
#include <memory>

struct Rule {
    DWORD targetPid;
    bool allow;
    bool Match(DWORD pid) const { return targetPid == pid; }
};

class RuleManager {
private:
    std::atomic<std::shared_ptr<std::vector<Rule>>> m_activeRules;

public:
    RuleManager() : m_activeRules(std::make_shared<std::vector<Rule>>()) {}

    bool CheckPermission(DWORD pid) {
        auto rules = m_activeRules.load(); // 原子加载,无任何锁开销
        bool result = false;
        for (const auto& rule : *rules) {
            if (rule.Match(pid)) {
                result = rule.allow;
                break;
            }
        }
        return result;
    }

    void AddRule(const Rule& newRule) {
        auto oldRules = m_activeRules.load();
        auto newRules = std::make_shared<std::vector<Rule>>(*oldRules);
        newRules->push_back(newRule);
        m_activeRules.store(newRules); // 原子替换,旧列表自动回收
    }
};

这个方案的读操作完全无锁,但写操作需要复制整个规则列表,适合规则数量不多的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 19:24:52