C++后端开发(3.2.4)——手写死锁检测组件


小节提纲

死锁现象以及原理
pthread_mutex_lock/pthread_mutex_unlock disym的实现
有向图的构建
有向图dfs判断环的存在
三个原语操作lock_before,lock_after,unlock_after
死锁检程线程的实现

死锁的四个必要条件和解决办法

dlsym用法

1 死锁现象以及原理

1.1 死锁概念及产生原理

概念: 多个并发进程因争夺系统资源而产生相互等待的现象。
原理: 当一组进程中的每个进程都在等待某个事件发生,而只有这组进程中的其他进程才能触发该事件,这就称这组进程发生了死锁。
本质原因

  1. 系统资源有限。
  2. 进程推进顺序不合理。

1.2 死锁产生的4个必要条件

  1. 互斥: 某种资源一次只允许一个进程访问,即该资源一旦分配给某个进程,其他进程就不能再访问,直到该进程访问结束。
  2. 占有且等待: 一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源。
  3. 不可抢占: 别人已经占有了某项资源,你不能因为自己也需要该资源,就去把别人的资源抢过来。
  4. 循环等待: 存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源。

当以上四个条件均满足,必然会造成死锁,发生死锁的进程无法进行下去,它们所持有的资源也无法释放。这样会导致CPU的吞吐量下降。所以死锁情况是会浪费系统资源和影响计算机的使用性能的。那么,解决死锁问题就是相当有必要的了。

1.3 死锁举例

死锁,是指多个线程或者进程在运行过程中因争夺资源而造成的一种僵局,当进程或者线程处于这种僵持状态,若无外力作用,它们将无法再向前推进。如下图所示,线程 A 想获取线程 B 的锁,线程 B 想获取线程 C 的锁,线程 C 想获取线程 D 的锁, 线程 D 想获取线程 A 的。
锁,从而构建了一个资源获取环。
在这里插入图片描述

2 死锁检测实现

资源获取环可以采用图来存储, 使用有向图来存储。 线程 A 获取线程 B 已占用的锁,则为线程 A 指向线程 B。 如何为线程 B 已占用的锁?运行过程线程 B 获取成功的锁。
检测的原理采用另一个线程定时对图进程检测是否有环的存在

2.1 有向图的构建

2.1.1 图相关结构体

enum Type
{
   
    PROCESS,
    RESOURCE
};

struct source_type
{
   
    uint64 id;
    enum Type type;

    uint64 lock_id;
    int degress;
};

struct vertex
{
   
    struct source_type s;
    struct vertex *next;
};

struct task_graph
{
   
    struct vertex list[MAX];
    int num;

    struct source_type locklist[MAX];
    int lockidx;

    pthread_mutex_t mutex;
};

struct task_graph *tg = NULL;
int path[MAX + 1];
int visited[MAX];
int k = 0;
int deadlock = 0;

2.1.2 图算法,检测成环

// 创造顶点
struct vertex *create_vertex(struct source_type type)
{
   
    struct vertex *tex = (struct vertex *)malloc(sizeof(struct vertex));

    tex->s = type;
    tex->next = NULL;

    return tex;
}

// 搜索某个顶点
int search_vertex(struct source_type type)
{
   
    int i = 0;

    for (i = 0; i < tg->num; i++)
    {
   
        if (tg->list[i].s.type == type.type && tg->list[i].s.id == type.id)
        {
   
            return i;
        }
    }

    return -1;
}

// 添加顶点
void add_vertex(struct source_type type)
{
   
    if (search_vertex(type) == -1)
    {
   
        tg->list[tg->num].s = type;
        tg->list[tg->num].next = NULL;
        tg->num++;
    }
}

// 增加一条边
int add_edge(struct source_type from, struct source_type to)
{
   
    add_vertex(from);
    add_vertex(to);

    struct vertex *v = &(tg->list[search_vertex(from)]);

    while (v->next != NULL)
    {
   
        v = v->next;
    }

    v->next = create_vertex(to);
}

// 修改边
int verify_edge(struct source_type i, struct source_type j)
{
   
    if (tg->num == 0)
        return 0;

    int idx = search_vertex(i);
    if (idx 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何蔚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值