1 常见的锁概念
1-1 死锁
死锁是指在⼀组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所站⽤不会
释放的资源⽽处于的⼀种永久等待状态。
所谓死锁就是我在申请一把锁的时候我持有这个锁然后我没有释放的情况下又去申请了一把锁这种情况就会导致死锁
造成的结果是
1-2 死锁得四个必要条件
互斥条件 一个资源每次只能被一个执行流使用
请求与保持条件
一个执行流因申请资源而堵塞时,对持有的资源也不进行释放
不剥夺条件:⼀个执⾏流已获得的资源,在末使⽤完之前,不能强⾏剥夺
循环等待条件:若⼲执⾏流之间形成⼀种头尾相接的循环等待资源的关系
1-3 避免死锁
避免死锁有4个条件
条件1: 锁排序(破坏循环等待)
// 通过内存地址强制排序
void safe_op(std::mutex& mtxA, std::mutex& mtxB) {
auto& first = std::min(&mtxA, &mtxB, std::less<void*>());
auto& second = std::max(&mtxA, &mtxB, std::less<void*>());
std::lock_guard<std::mutex> lk1(*first);
std::lock_guard<std::mutex> lk2(*second);
// 安全操作共享资源
}
条件2 RAII守卫 + 作用域控制(自动释放)
{
std::lock_guard<std::mutex> lk1(mtx1); // 自动释放
// 操作资源1...
{ // 限制锁作用域
std::lock_guard<std::mutex> lk2(mtx2);
// 操作资源1+2...
} // lk2自动解锁
// 此处仅持有mtx1
} // lk1自动解锁
条件3 原子操作替代锁(避免互斥)
std::atomic<int> counter(0);
// 无锁自增
void safe_increment() {
counter.fetch_add(1, std::memory_order_relaxed);
}
条件4 标准库联合锁(破坏持有并等待)
#include <mutex>
void safe_transaction() {
std::lock(mtx1, mtx2); // 原子化锁定多个互斥量
std::lock_guard<std::mutex> lk1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> lk2(mtx2, std::adopt_lock);
// 安全操作双资源
} // 自动解锁