当前位置: 首页 > news >正文

[ Linux ] 死锁以及如何避免死锁

目录

1.什么是死锁?

死锁

2.模拟死锁情况

3.死锁四个必要条件

4.避免死锁的方法

5.避免死锁的算法

银行家算法(了解为主)


1.什么是死锁?

死锁

  • 死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用不会释放的资源而处于的一种永久等待的状态。

2.模拟死锁情况

我们使用多线程模拟一个死锁的情况。

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <mutex>

using namespace std;

pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexB = PTHREAD_MUTEX_INITIALIZER;
void* startRoutine1(void* args)
{
    while(true)
    {
        pthread_mutex_lock(&mutexA);
        sleep(1);
        pthread_mutex_lock(&mutexB);
        cout<<"我是线程1,我的tid"<<pthread_self()<<endl;
        pthread_mutex_unlock(&mutexB);
        pthread_mutex_unlock(&mutexA);
    }

}

void* startRoutine2(void* args)
{
  while(true)
    {
        pthread_mutex_lock(&mutexB);
        sleep(1);
        pthread_mutex_lock(&mutexA);
        cout<<"我是线程2,我的tid"<<pthread_self()<<endl;
        pthread_mutex_unlock(&mutexB);
        pthread_mutex_unlock(&mutexA);
    }
}


int main()
{
    pthread_t t1,t2;

    pthread_create(&t1,nullptr,startRoutine1,nullptr);
    pthread_create(&t2,nullptr,startRoutine2,nullptr);
    
    pthread_join(t1,nullptr);
    pthread_join(t2,nullptr);
    return 0;
}

当上面这段程序运行起来时,线程1和线程2会同时调用各自的startRountine函数,由于mutexA和mutexB均为临界资源只有一份,而在程序中,线程1会先申请mutexA,线程2会先申请mutexB,而当他们申请结束时都会等待1秒(这里等待一秒是确保两个线程各自占有一把锁),一秒休眠结束后,当线程1想要申请mutexB时,由于mutexB已经被线程2占有且未释放,因此线程1将阻塞等待mutexB的释放;同理,线程2也会阻塞等待mutexA。此时,各线程均占有不会释放的资源mutex,并且互相申请了其他线程所占用不会释放的资源而除以一种永久等待的状态。我们把这种状态就称为死锁。当程序运行起来时,我们也能看到程序并没有什么打印结果.....

我们使用监控脚本查看3个线程任然在运行之中

while :; do ps -aL | grep mythread ; sleep 1;echo "---------------";done

3.死锁四个必要条件

死锁的必要条件:死锁情况一旦发生,这四个条件一定都要满足。如果有一个没有产生,那死锁的条件便不成立。

  1. 互斥条件:一个资源每次只能被一个执行流使用
  2. 请求与保持条件:一个执行流因请求资源而阻塞时,对已获得的资源保持不败
  3. 不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能强行剥夺
  4. 循环等待条件:若干执行流之间形成一种头尾相接的循环等待资源的关系

4.避免死锁的方法

  • 破坏死锁的四个必要条件
  • 加锁顺序一致
  • 避免锁未释放的场景
  • 资源一次性分配

5.避免死锁的算法

银行家算法(了解为主)

我们在当时将锁的时候,查看过pthread_mutex_lock和pthread_mutex_unlock函数,我们也使用了,那么大家还记不记得其中还有一个trylock。这个函数就是用来尝试申请,如果是安全序列则会正式分配,否则不会分配。

核心思想:

银行家算法是一种最有代表性的避免死锁的算法。在避免死锁方法中允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次分配资源的安全性,若分配不会导致系统进入不安全状态,则分配,否则等待。

相关文章:

  • 网站建设需要注意的问题/国内疫情最新消息
  • 域名 空间 网站制作/网络营销五种方法
  • 农村自建房设计网站/长春关键词优化排名
  • 郑州快速建站公司/广告代理
  • 推荐优秀网站/昆明seo网站建设
  • 和平区网站制作/小程序推广
  • JavaScript时间格式化插件,返回指定字符串
  • 多播网络(Multicast)应用权限
  • 使用mosquitto部署MQTT服务
  • Zookeeper 4 Zookeeper JavaAPI 操作 4.7 Curator API 常用操作【Watch 事件监听】
  • 【发表案例】计算机科学类SCI,仅1个月零6天录用,涵盖软件、信息、数据云计算、网络、建模等研究方向
  • 【JavaScript】15_debug,立即执行函数 与 严格模式
  • 智能制造数字化转型难点有哪些?
  • 【UE4 第一人称射击游戏】06-设置动画角色2
  • U-net
  • pytest-需要模块相应的库
  • VSCode连GitHub的代理服务器配置和获取历史版本命令
  • 笔试训练(4)