返回
极少共享访问下 Windows 系统资源锁定最佳实践
windows
2024-03-02 08:10:57
高效锁定 Windows 系统资源:应对极少共享访问情况
问题概况
在 C++11 中,我们面临着一个棘手的锁定时机选择问题。我们的 C++ 类管理着一系列规则,需要确保在添加或删除规则时不会进行任何检查,但由于添加和删除规则的情况极其罕见,因此在 99.9% 的检查情况下,不需要进行锁定。
潜在解决方案
有多种潜在解决方案,包括:
- std::mutex: 最简单的方法,但即使在 99.9% 不需要锁定时也必须保持锁定,会造成不必要的开销。
- 临界区 (Critical Section): 比 std::mutex 慢,尤其是在 Windows 8.1+ 中。
- WinAPI 互斥体: Windows 系统中的原语,非常高效,适合写入操作罕见的情况。
- 读写锁: 允许多个线程同时读取资源,但只能允许一个线程写入资源。
推荐解决方案:WinAPI 互斥体
考虑到极少需要共享访问的情况,WinAPI 互斥体 是我们的最佳选择。互斥体在 Windows 系统中非常高效,非常适合这种场景,其中写入操作很少见。
示例实现
以下示例代码展示了如何使用 WinAPI 互斥体:
#include <Windows.h>
class RuleList {
private:
HANDLE mutex;
std::list<Rule> rules;
public:
RuleList() {
// 创建互斥体
mutex = CreateMutex(NULL, FALSE, NULL);
}
~RuleList() {
// 释放互斥体
CloseHandle(mutex);
}
void addRule(const Rule& rule) {
// 获取互斥体锁
WaitForSingleObject(mutex, INFINITE);
// 添加规则
rules.push_back(rule);
// 释放互斥体锁
ReleaseMutex(mutex);
}
void removeRule(const Rule& rule) {
// 获取互斥体锁
WaitForSingleObject(mutex, INFINITE);
// 删除规则
rules.remove(rule);
// 释放互斥体锁
ReleaseMutex(mutex);
}
bool check(const PID& pid) {
// 无需锁定,因为规则不会在检查期间发生改变
for (const Rule& rule : rules) {
if (rule.appliesTo(pid)) {
return true;
}
}
return false;
}
};
优点
- 高效,特别是对于共享访问极少的情况
- 易于实现
- 与 Windows 系统高度集成
缺点
- 需要使用 Windows 专用 API
- 可能比其他方法更难以移植到其他平台
常见问题解答
1. 为什么在没有竞争的情况下使用互斥体?
为了确保在添加或删除规则时不会进行任何检查,无论并发情况如何。
2. 是否可以同时拥有多个互斥体?
是的,一个类可以拥有多个互斥体,每个互斥体用于保护不同的资源或操作。
3. 互斥体如何防止死锁?
WinAPI 互斥体实现了死锁检测和预防机制。
4. 如何正确处理互斥体的错误?
在创建、获取或释放互斥体时,应检查错误代码并采取适当措施。
5. 是否有其他非锁定的机制可以解决此问题?
可以考虑使用原子操作或基于版本号的并发控制。然而,这些方法可能并不总是可行,具体取决于具体场景。
总结
通过使用 WinAPI 互斥体,我们可以在极少需要共享访问的情况下高效地锁定 Windows 系统资源。这种方法易于实现,与 Windows 系统高度集成,并且提供所需的效率。