死锁检测组件实现

简介: 死锁检测组件实现

       当线程多了之后,一部分线程做数据处理,一个线程做日志同步,还有做网络的线程及操作数据库的线程,当线程比较多的时候出现死锁的概率是很高的;

       使用htop去看cpu的使用情况,cpu占用率总是百分之百,这个时候就是进入了死锁的状态,一直在等一直在等;

       死锁的状态,是由于线程无法正常获取资源;如下1,2,3,4代表资源,A,B,C,D代表线程,开始1,2,3,4分别被A,B,C,D线程使用着,但是此时A又需要使用2,B需要使用4,C需要使用1,D需要使用3;而这些资源又已经被占用了无法竞争到,就产生了死锁;判断是否产生死锁就只要看是否有出现这样的环出现就可以了;

如何知道资源(比如pthread_mutex_lock(mutex))被哪个线程占用了呢?这个是不知道的,没办法判断的;

构建并打印死锁,通过hook机制,从而使得调用pthread_mutrex_lock,pthread_mutex_unlock时调用我们自己实现的对应函数;

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
typedef int (*pthread_mutex_lock_t)(pthread_mutex_t *mutex);
typedef int (*pthread_mutex_unlock_t)(pthread_mutex_t *mutex);
pthread_mutex_lock_t pthread_mutex_lock_f;
pthread_mutex_unlock_t pthread_mutex_unlock_f;
int pthread_mutex_lock(pthread_mutex_t *mutex) {
    pthread_t selfid = pthread_self();
    pthread_mutex_lock_f(mutex);
    printf("pthread_mutex_lock: %ld, %p\n", selfid, mutex);
}
int pthread_mutex_unlock(pthread_mutex_t *mutex) {
    pthread_t selfid = pthread_self();
    pthread_mutex_unlock_f(mutex);
    printf("pthread_mutex_unlock: %ld, %p\n", selfid, mutex);
}
void init_hook(void) {
    pthread_mutex_lock_f = dlsym(RTLD_NEXT, "pthread_mutex_lock");
    pthread_mutex_unlock_f = dlsym(RTLD_NEXT, "pthread_mutex_unlock");
}
#if 1
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex4 = PTHREAD_MUTEX_INITIALIZER;
void *thread_funcA(void *arg) {
    pthread_mutex_lock(&mutex1);
    sleep(1);
    pthread_mutex_lock(&mutex2);
    printf("thread_funcA\n");
    pthread_mutex_unlock(&mutex2);
    pthread_mutex_unlock(&mutex1);
}
void *thread_funcB(void *arg) {
    pthread_mutex_lock(&mutex2);
    sleep(1);
    pthread_mutex_lock(&mutex3);
    printf("thread_funcB\n");
    pthread_mutex_unlock(&mutex3);
    pthread_mutex_unlock(&mutex2);
}
void *thread_funcC(void *arg) {
    pthread_mutex_lock(&mutex3);
    sleep(1);
    pthread_mutex_lock(&mutex4);
    printf("thread_funcC\n");
    pthread_mutex_unlock(&mutex4);
    pthread_mutex_unlock(&mutex3);
}
void *thread_funcD(void *arg) {
    pthread_mutex_lock(&mutex4);
    sleep(1);
    pthread_mutex_lock(&mutex1);
    printf("thread_funcD\n");
    pthread_mutex_unlock(&mutex1);
    pthread_mutex_unlock(&mutex4);
}
int main() {
    init_hook();
    pthread_t tida, tidb, tidc, tidd;
    pthread_create(&tida, NULL, thread_funcA, NULL);
    pthread_create(&tidb, NULL, thread_funcB, NULL);
    pthread_create(&tidc, NULL, thread_funcC, NULL);
    pthread_create(&tidd, NULL, thread_funcD, NULL);
    pthread_join(tida, NULL);
    pthread_join(tidb, NULL);
    pthread_join(tidc, NULL);
    pthread_join(tidd, NULL);
    return 0;
}
#endif

       死锁检测,可以通过构建有向图判断是否有环来检测;图的构建方式,可以通过矩阵和邻接表;以邻接表,若线程1申请线程2的资源,而该资源又被线程2占用着,我们就将线程1的next指针指向线程2,表示线程1生成的资源已经被线程2占用了;

       新增线程并在线程中有调用pthread_mutex_lock的时候就相当于在图上新增节点,新增边则是在当调用pthread_mutex_lock发现资源被其他线程占用的时候;

目录
相关文章
|
3月前
|
Java 测试技术 PHP
父子任务使用不当线程池死锁怎么解决?
在Java多线程编程中,线程池有助于提升性能与资源利用效率,但若父子任务共用同一池,则可能诱发死锁。本文通过一个具体案例剖析此问题:在一个固定大小为2的线程池中,父任务直接调用`outerTask`,而`outerTask`再次使用同一线程池异步调用`innerTask`。理论上,任务应迅速完成,但实际上却超时未完成。经由`jstack`输出的线程调用栈分析发现,线程陷入等待状态,形成“死锁”。原因是子任务需待父任务完成,而父任务则需等待子任务执行完毕以释放线程,从而相互阻塞。此问题在测试环境中不易显现,常在生产环境下高并发时爆发,重启或扩容仅能暂时缓解。
|
存储 监控 算法
实现死锁检测组件
实现死锁检测组件
58 0
|
6月前
|
存储 监控 程序员
线程死锁检测组件逻辑与源码
线程死锁检测组件逻辑与源码
84 2
|
6月前
|
存储
动手实现死锁检测组件(通过hook与有向图实现)
动手实现死锁检测组件(通过hook与有向图实现)
81 1
|
6月前
|
存储
死锁检测组件
死锁检测组件
35 0
|
6月前
|
存储 安全 C语言
死锁检测组件原理及代码实现
死锁检测组件原理及代码实现
|
11月前
|
算法 调度
死锁原因及死锁检测组件的实现
死锁原因及死锁检测组件的实现
119 0
|
SQL 存储 Oracle
19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍|学习笔记
快速学习19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍
19 PostgreSQL 锁类型,锁模式,锁冲突,死锁检测的介绍|学习笔记
|
算法 安全 Java
死锁的原理
之前在学校学习过程中,很少写多进程的代码,虽然操作系统中学过死锁相关的内容,但考试过后也基本就忘记了,后来自己也遇到过有些多进程死锁的情况,再加上看了有些资料,对死锁才算是有了有些深入的理解。
81 0