C/C++基于线程的并发编程(三):死锁

什么叫死锁

死锁(deadlock),指的是多线程(多进程)在运行中被阻塞的情况。如下图所示,进程1拥有资源1并等待资源2,进程2拥有资源2等待资源1。进程1需要等待资源2才会释放资源1,进程2需要等待资源1才会释放资源2,导致两个进程相互阻塞。死锁就好比两个人面对面碰上对方,两人互不相让,都在等待对方先让路。
在这里插入图片描述

C++代码死锁例子

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mutex;

void func() {
    std::cout << "func try to lock mutex" << std::endl;
    std::lock_guard<std::mutex> locker(mutex);	// thread线程申请锁资源, 等待锁释放
    std::cout << "func try to lock mutex success" << std::endl;
}

int main() {
    std::cout << "main try to lock mutex" << std::endl;
    std::lock_guard<std::mutex> locker(mutex);  // 主线程占用mutex
    std::thread thread(func);

    thread.join();

    std::cout << "main try to lock mutex success" << std::endl;
    return 0;
}

上述代码申请了共享mutex资源,在主线程先申请锁资源并上锁。运行至thread线程时,也申请所资源,并等待锁释放。主线程在等待thread线程结束才会释放锁资源,thread线程也在等主线程释放mutex资源才会继续运行,所以程序处于死锁状态。输出如下:

main try to lock mutex
func try to lock mutex

"func try to lock mutex success"和"main try to lock mutex success"均无法输出。

产生死锁的必要条件

当同时满足以下四个条件就会引发死锁:
互斥: 资源在同一时间只能被一个线程(进程)占用,无法在多个线程(进程)之间共享。
保持和等待: 一个线程(进程)至少占用一个资源并且等待被其他线程(进程)占用的资源。
无抢占: 资源只能等待某个线程(进程)释放才能被其他线程(进程)。
循环等待: 一系列线程(进程)以循环的形式相互等待资源的释放。

如何预防死锁

从产生死锁的四个必要条件为方向,只要不满足其中一条就可以避免死锁。
避免互斥: 不申请共享资源,所有资源申请为独占资源。
避免保持和等待: 保证线程(进程)请求资源时,该资源不被其他资源占有。要求线程(进程)在开始执行前就请求并分配所有资源,或者允许线程(进程)在没有资源时才能申请资源。这样的缺点就是资源利用率低,资源申请都是饿汉模式。
避免无抢占:

  1. 如果一个占用很多资源的线程(进程)在请求其他资源,并且请求的资源不能马上分配给该线程(进程)时,该线程(进程)占用的所有资源都被释放。
  2. 建立资源等待列表,将线程(进程)的被抢占资源添加到等待列表中。
  3. 当线程(进程)重新获取旧资源以及正在请求的新资源时,线程(进程)重新启动。
    避免循环等待: 强制所有资源的申请顺序,并要求所有线程(进程)以一定顺序请求资源。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值