-
Notifications
You must be signed in to change notification settings - Fork 385
ipc::sync::mutex
mutouyun edited this page Dec 9, 2025
·
1 revision
进程间互斥锁,用于保护跨进程的共享资源。支持命名和匿名两种模式。
namespace ipc {
namespace sync {
class mutex {
public:
mutex();
explicit mutex(char const *name);
~mutex();
void const *native() const noexcept;
void *native() noexcept;
bool valid() const noexcept;
bool open(char const *name) noexcept;
void close() noexcept;
void clear() noexcept;
static void clear_storage(char const * name) noexcept;
bool lock(std::uint64_t tm = ipc::invalid_value) noexcept;
bool try_lock() noexcept(false); // 可能抛出 std::system_error
bool unlock() noexcept;
};
} // namespace sync
} // namespace ipc| 成员 | 说明 |
|---|---|
mutex |
构造函数 |
~mutex |
析构函数 |
open |
打开一个命名的mutex |
close |
关闭mutex |
clear |
清理mutex资源 |
clear_storage |
清理指定名称的mutex存储 |
lock |
加锁,可设置超时 |
try_lock |
尝试加锁(非阻塞) |
unlock |
解锁 |
valid |
检查mutex是否有效 |
native |
获取原生句柄 |
/*A*/ mutex();
/*B*/ explicit mutex(char const *name);- A. 默认构造函数,创建一个匿名mutex(仅用于进程内同步)
- B. 创建或打开一个命名的mutex(用于进程间同步)
| 参数 | 说明 |
|---|---|
name |
char const *,mutex的名称。使用相同名称可以在不同进程间共享mutex |
~mutex();析构函数。自动释放mutex资源。
bool open(char const *name) noexcept;打开一个命名的mutex。如果mutex不存在,会自动创建。
| 参数 | 说明 |
|---|---|
name |
char const *,mutex的名称 |
| 返回值 | 说明 |
|---|---|
true |
打开成功 |
false |
打开失败 |
void close() noexcept;关闭mutex。释放相关资源。
void clear() noexcept;清理已打开mutex的所有资源,包括共享内存。
static void clear_storage(char const * name) noexcept;静态方法。清理指定名称的mutex存储资源。
| 参数 | 说明 |
|---|---|
name |
char const *,要清理的mutex名称 |
bool lock(std::uint64_t tm = ipc::invalid_value) noexcept;加锁操作。如果mutex已被其他线程/进程持有,则阻塞等待直到获得锁或超时。
| 参数 | 说明 |
|---|---|
tm |
std::uint64_t,超时时间(毫秒)。默认为ipc::invalid_value(无限等待) |
| 返回值 | 说明 |
|---|---|
true |
成功获得锁 |
false |
超时未获得锁 |
bool try_lock() noexcept(false); // 可能抛出 std::system_error尝试加锁(非阻塞)。立即返回,不等待。
| 返回值 | 说明 |
|---|---|
true |
成功获得锁 |
false |
未获得锁(mutex已被持有) |
| 异常 | 说明 |
|---|---|
std::system_error |
系统错误时抛出 |
bool unlock() noexcept;解锁操作。释放mutex。
| 返回值 | 说明 |
|---|---|
true |
解锁成功 |
false |
解锁失败 |
注意:只有持有锁的线程/进程才能解锁。
bool valid() const noexcept;检查mutex是否有效(已打开)。
| 返回值 | 说明 |
|---|---|
true |
mutex有效 |
false |
mutex无效或未打开 |
/*A*/ void const *native() const noexcept;
/*B*/ void *native() noexcept;获取平台相关的原生mutex句柄。
- A. const版本
- B. 非const版本
| 返回值 | 说明 |
|---|---|
void* |
原生mutex句柄指针 |
#include "libipc/mutex.h"
#include "libipc/shm.h"
#include <iostream>
// 共享内存中的计数器
struct shared_counter {
int count;
};
void increment_counter(int process_id) {
// 打开共享互斥锁
ipc::sync::mutex mtx("counter_mutex");
// 打开共享内存
ipc::shm::handle shm("counter_shm", sizeof(shared_counter));
auto* counter = static_cast<shared_counter*>(shm.get());
for (int i = 0; i < 1000; ++i) {
// 加锁
if (mtx.lock()) {
// 临界区:访问共享资源
counter->count++;
std::cout << "Process " << process_id
<< ": count = " << counter->count << std::endl;
// 解锁
mtx.unlock();
}
}
}
int main() {
// 初始化共享内存
{
ipc::shm::handle shm("counter_shm", sizeof(shared_counter));
auto* counter = static_cast<shared_counter*>(shm.get());
counter->count = 0;
}
// 启动多个进程(这里用线程模拟)
std::thread t1(increment_counter, 1);
std::thread t2(increment_counter, 2);
std::thread t3(increment_counter, 3);
t1.join();
t2.join();
t3.join();
// 清理
ipc::sync::mutex::clear_storage("counter_mutex");
return 0;
}void worker(int id) {
ipc::sync::mutex mtx("work_mutex");
// 尝试获得锁,不阻塞
try {
if (mtx.try_lock()) {
std::cout << "Worker " << id << " got the lock" << std::endl;
// 执行工作
std::this_thread::sleep_for(std::chrono::milliseconds(100));
mtx.unlock();
} else {
std::cout << "Worker " << id << " failed to get lock, doing other work" << std::endl;
// 做其他不需要锁的工作
}
} catch (const std::system_error& e) {
std::cerr << "System error: " << e.what() << std::endl;
}
}void timeout_example() {
ipc::sync::mutex mtx("timeout_mutex");
// 尝试在1000ms内获得锁
if (mtx.lock(1000)) {
std::cout << "Got lock within 1 second" << std::endl;
// 临界区
// ...
mtx.unlock();
} else {
std::cout << "Timeout: failed to get lock in 1 second" << std::endl;
}
}// 简单的锁守卫类
class mutex_guard {
ipc::sync::mutex& mtx_;
bool locked_;
public:
explicit mutex_guard(ipc::sync::mutex& mtx)
: mtx_(mtx), locked_(false) {
locked_ = mtx_.lock();
}
~mutex_guard() {
if (locked_) {
mtx_.unlock();
}
}
bool owns_lock() const { return locked_; }
// 禁止拷贝
mutex_guard(const mutex_guard&) = delete;
mutex_guard& operator=(const mutex_guard&) = delete;
};
// 使用示例
void safe_access() {
ipc::sync::mutex mtx("my_mutex");
{
mutex_guard guard(mtx);
if (guard.owns_lock()) {
// 自动管理锁的生命周期
// 在作用域结束时自动解锁
// 访问共享资源...
}
} // guard析构,自动解锁
}在POSIX系统上,ipc::sync::mutex使用robust mutex特性,能够从死锁所有者进程崩溃的情况中恢复:
void robust_mutex_example() {
ipc::sync::mutex mtx("robust_mutex");
// 如果之前持有锁的进程崩溃了,lock()仍然能够成功
// 库会自动处理EOWNERDEAD状态
if (mtx.lock()) {
std::cout << "Got lock (may have recovered from dead owner)" << std::endl;
// 此时可能需要检查和修复共享数据的一致性
// ...
mtx.unlock();
}
}- 基于POSIX pthread mutex
- 支持robust mutex特性(自动处理死锁所有者)
- 支持进程共享(PTHREAD_PROCESS_SHARED)
- 使用共享内存实现
- 基于Windows Mutex对象
- 通过命名Mutex实现进程间同步
- 自动处理所有者进程终止的情况
- 命名空间:不同名称的mutex是完全独立的
-
死锁避免:
- 始终在同一线程/进程中配对lock()和unlock()
- 考虑使用RAII包装类(如上述mutex_guard)
- 避免嵌套锁,或者保持固定的加锁顺序
-
异常安全:
try_lock()可能抛出std::system_error,需要适当处理 -
超时参数:
lock()的默认超时是无限等待,生产环境建议使用明确的超时值 -
清理资源:程序退出前调用
clear()或clear_storage()清理共享资源 - 不支持递归:同一线程不能对已持有的mutex再次加锁(会导致死锁)
- 性能考虑:进程间mutex比进程内mutex开销更大,仅在必要时使用
-
ipc::sync::semaphore- 进程间信号量 -
ipc::sync::condition- 进程间条件变量 -
ipc::spin_lock- 自旋锁 -
ipc::rw_lock- 读写锁