假定我们需要同时获取多个锁,那么std::lock函数和std::scope_lock<>模板可以帮助防范死锁。

class some_bi_obj;
void swap(some_bi_obj& lhs, some_bi_obj& rhs);

class X {
private:
    some_bi_obj some_details;
    std::mutex m;
public:
    X(some_bi_obj const& sd) : some_details(sd) {}
    friend void swap(X& lhs, X& rhs) {
        if (&lhs == &rhs) return;
        std::lock(lhs.m, rhs.m);    // 锁定两个互斥
        std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock); // 指明mutex已经被锁了
        std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock); // 指明mutex已经被锁了
        swap(lhs.some_details, rhs.some_details);
    }
};

或者使用scope_lock也可以

一个函数如果要锁住相同类型的多个对象,为了保证始终按相同的顺序加锁,我们可以比较mutex对象的地址,始终先加锁地址较小的mutex。

#include <iostream>
#include <mutex>

// 定义两个互斥锁对象
std::mutex mutex1;
std::mutex mutex2;

void lockMutexesInOrder(std::mutex* mutexA, std::mutex* mutexB) {
    // 比较锁对象的地址,将较小地址的锁先锁住
    if (mutexA < mutexB) {
        mutexA->lock();
        mutexB->lock();
    } else {
        mutexB->lock();
        mutexA->lock();
    }
}

void unlockMutexes(std::mutex* mutexA, std::mutex* mutexB) {
    // 解锁两个互斥锁
    mutexA->unlock();
    mutexB->unlock();
}

int main() {
    // 使用函数按顺序加锁和解锁两个互斥锁
    lockMutexesInOrder(&mutex1, &mutex2);
    
    // 此处放置需要在拥有锁的情况下执行的代码

    unlockMutexes(&mutex1, &mutex2);

    return 0;
}