首页 > 社交 > 科普中国

死锁检测实现

常驻编辑 科普中国 2022-09-25 死锁   钩子   遍历   节点   线程   解锁   函数   加锁   后台   资源
YEQ拜客生活常识网

//dfs深度遍历
int dfs(int idx){

    struct vertex *v = &tg->list[idx];
    
    if(visited[idx] == 1){//有环
        path[k++] = idx;
        print_deadlock();
        deadlock = 1;
        return 0;
    }

    visited[idx] =1;//被遍历到了,赋值为1,保证同一个节点只能遍历一次
    path[k++] = idx;
    while(v->next !=NULL){
        dfs(search_vertex(v->next->d));
        k--;
        v = v->next;
    }
    return 1;
}

//遍历图,任意从图的一个节点出发,对每一个节点进行dfs遍历
int search_for_cycle(int idx){

    struct vertex *v = &tg->list[idx];
    visited[idx] = 1;
    k = 0;
    path[k++] = idx;

    while(v->next != NULL){
        int i = 0;
        for (; i < tg->num; i++)
        {
            if(i == idx){
                continue;
            }
            visited[i] = 0;
        }

        for(i = 1; i <= THREAD_MAX; i++){
            path[i] = -1;
        }
        k = 1;
        
        dfs(search_vertex(v->next->d));
        v = v->next;
    }
}

(4)启动检测

C++后台开发架构师免费学习地址:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂
YEQ拜客生活常识网

另外还整理一些C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以自行添加点击 正在跳转 群文件共享YEQ拜客生活常识网

YEQ拜客生活常识网

  启动线程定时检测图是否有环,代码如下。YEQ拜客生活常识网

//从第0个节点开始dfs
void check_dead_lock(){

    int i = 0;
    deadlock = 0;
    for(;i < tg->num; i++){
        if(deadlock == 1) break;
        search_for_cycle(i);
    }
    if(deadlock == 0){
        printf("no deadlock
");
    }
}

//检测锁线程func
static void *thread_func(void *args){

    while(1){
        sleep(5);
        check_dead_lock();
    }
}

//启动检测锁线程
void start_check(){

    tg = (struct graph*)malloc(sizeof(struct graph));
    tg->num = 0;
    tg->lockidx = 0;

    pthread_t tid;
    pthread_create(&tid,NULL,thread_func,NULL);
}

(5)钩子hook

  为了不改变项目原代码,使用hook在应用程序调用系统加锁、解锁API时进行劫持,使其实际调用的是应用程序定义的加锁、解锁API;再进行加锁、解锁前,我们先去理解3个状态,加锁前、加锁后、解锁后,即:lock_before、lock_after、unlock_after,通过这三个函数与图构建起来,具体实现如下。YEQ拜客生活常识网

//1.没有被其他线程占用,不用处理
//2.有被其它线程占用,就要把边构建起来
//    添加边
void lock_before(uint64 thread_id, uint64 lockid){

    int idx = 0;
    for(;idx < tg->lockidx;idx++){
        if(tg->locklist[idx].lock_id == lockid){
            struct node from;
            from.thread_id = thread_id;
            add_vertex(&from);

            struct node to;
            to.thread_id = tg->locklist[idx].thread_id;
            tg->locklist[idx].degress++;
            add_vertex(&to);

            if(!verifty_edge(&from, &to)){
                add_edge(&from, &to);//添加边
            }
        }
    }
}


YEQ拜客生活常识网

//1.没有被其它线程占用
//先加入一个节点add_edge
//2.有被占用
//是进不来lock_after的
//
//等unlock_after 释放后
//        mtx没有主人
void lock_after(uint64 threadid, uint64 lockid) {

    int idx = 0;
    if(-1 == (idx = search_lock(lockid))){
        int eidx = search_empty_lock();
        tg->locklist[eidx].thread_id = threadid;
        tg->locklist[eidx].lock_id = lockid;

        inc(&tg->lockidx, 1);
    }else{
        struct node from;
        from.thread_id = threadid;

        struct node to;
        to.thread_id = tg->locklist[idx].thread_id;
        tg->locklist[idx].degress--;

        if(verifty_edge(&from, &to)){
            remove_edge(&from, &to);//不在死锁检测的圈里面了,所以删除边
        }
        tg->locklist[idx].thread_id = threadid;
    }
}


YEQ拜客生活常识网

void unlock_after(uint64 threadid, uint64 lockid) {

    int idx = search_lock(lockid);
    if(tg->locklist[idx].degress == 0){
        tg->locklist[idx].thread_id = 0;
        tg->locklist[idx].lock_id = 0;
    }
}    

相关阅读:

  • 越南要涨工资了,却暴露一个大问题
  • 从通用的协议栈层面来优化Redis性能的实践
  • Java中各种锁的介绍
  • 盐与献祭国王支线任务怎么做
  • 动手写一个模板方法模式(Java版)
  • 荷兰的首都在阿姆斯特丹,政府却在海牙
  • 云原生(十四)
  • 第五人格萌新玩家应该选什么监管?我来给大家说一下
  • 你遇到过最差劲的老师是谁?
  • 五个越玩越快乐的英雄,上分娱乐两不误,还能搞对手心态
    • 网站地图 |
    • 声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不做权威认证,如若验证其真实性,请咨询相关权威专业人士。