Skip to content

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 获取原生句柄

构造函数

mutex

/*A*/ mutex();
/*B*/ explicit mutex(char const *name);
  • A. 默认构造函数,创建一个匿名mutex(仅用于进程内同步)
  • B. 创建或打开一个命名的mutex(用于进程间同步)
参数 说明
name char const *,mutex的名称。使用相同名称可以在不同进程间共享mutex

~mutex

~mutex();

析构函数。自动释放mutex资源。

资源管理

open

bool open(char const *name) noexcept;

打开一个命名的mutex。如果mutex不存在,会自动创建。

参数 说明
name char const *,mutex的名称
返回值 说明
true 打开成功
false 打开失败

close

void close() noexcept;

关闭mutex。释放相关资源。

clear

void clear() noexcept;

清理已打开mutex的所有资源,包括共享内存。

clear_storage

static void clear_storage(char const * name) noexcept;

静态方法。清理指定名称的mutex存储资源。

参数 说明
name char const *,要清理的mutex名称

锁操作

lock

bool lock(std::uint64_t tm = ipc::invalid_value) noexcept;

加锁操作。如果mutex已被其他线程/进程持有,则阻塞等待直到获得锁或超时。

参数 说明
tm std::uint64_t,超时时间(毫秒)。默认为ipc::invalid_value(无限等待)
返回值 说明
true 成功获得锁
false 超时未获得锁

try_lock

bool try_lock() noexcept(false);  // 可能抛出 std::system_error

尝试加锁(非阻塞)。立即返回,不等待。

返回值 说明
true 成功获得锁
false 未获得锁(mutex已被持有)
异常 说明
std::system_error 系统错误时抛出

unlock

bool unlock() noexcept;

解锁操作。释放mutex。

返回值 说明
true 解锁成功
false 解锁失败

注意:只有持有锁的线程/进程才能解锁。

状态查询

valid

bool valid() const noexcept;

检查mutex是否有效(已打开)。

返回值 说明
true mutex有效
false mutex无效或未打开

native

/*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;
}

使用 try_lock 避免阻塞

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;
    }
}

RAII 风格的锁管理

// 简单的锁守卫类
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析构,自动解锁
}

处理死锁所有者(Robust Mutex)

在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();
    }
}

平台差异

Linux / FreeBSD / QNX

  • 基于POSIX pthread mutex
  • 支持robust mutex特性(自动处理死锁所有者)
  • 支持进程共享(PTHREAD_PROCESS_SHARED)
  • 使用共享内存实现

Windows

  • 基于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 - 读写锁

Clone this wiki locally