BackendWorkerLock
是一个 进程内单例锁,用于确保 Quill 日志库在单个进程内只存在一个 BackendWorker
实例。主要解决以下问题:
问题场景 | 解决方案 |
---|---|
静态库被多个模块链接 | 通过命名锁检测冲突 |
DLL被重复加载 | 跨模块互斥量保护 |
多线程误创建 | 快速失败机制 |
_handle = CreateMutexA(nullptr, TRUE, name.data());
ERROR_ALREADY_EXISTS
精确检测重复实例name.data()
:包含进程ID的唯一名称(如 Local\QuillLock1234
)TRUE
:创建后立即获得所有权_sem = sem_open(name.data(), O_CREAT, 0644, 1);
sem_unlink(name.data()); // 立即取消文件系统关联
0644
:用户可读写,组和其他只读1
:二进制信号量#elif defined(__ANDROID__)
// disabled
sem_open
实现不完整if (GetLastError() == ERROR_ALREADY_EXISTS) {
QUILL_THROW(QuillError{
"Duplicate backend worker thread detected..."});
}
~BackendWorkerLock() {
#if defined(_WIN32)
ReleaseMutex(_handle);
CloseHandle(_handle);
#else
sem_post(_sem); // 释放锁
sem_close(_sem); // 关闭描述符
#endif
}
BackendWorkerLock(const BackendWorkerLock&) = delete;
BackendWorkerLock& operator=(const BackendWorkerLock&) = delete;
平台 | 锁类型 | 优势 |
---|---|---|
Windows | 命名Mutex | 内核级同步,可靠 |
Unix | 信号量+unlink | 无残留文件 |
Android | 无锁 | 兼容性优先 |
GetLastError()
区分:
nullptr
)ERROR_ALREADY_EXISTS
)sem_trywait
+ errno
快速判断sem_trywait
避免线程挂起sem_unlink
防止资源泄漏主程序(动态链接Quill)
└── 插件A(静态链接Quill)
└── 插件B(静态链接Quill)
BackendWorker
实例竞争日志文件// DLL热加载场景
void reload_module() {
auto old = worker;
worker = new BackendWorker(); // 被锁阻止
delete old;
}
/dev/shm
导致信号量冲突std::string name = "/QuillLock_" + get_container_id() + pid;
Global\
前缀的Mutex实现会话隔离# Linux查看信号量
ipcs -s
# Windows查看Mutex
Handle.exe -a Mutex
【技术人的鼓励】❤️ 如果这篇文章对您有帮助,欢迎点击打赏按钮支持博主!您的鼓励是我持续输出优质技术内容的动力,哪怕只是1元也足以让我感受到这份珍贵的认可。