死锁检测组件实现

简介: 死锁检测组件实现

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

       使用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发现资源被其他线程占用的时候;

目录
相关文章
|
5月前
|
Java 测试技术 PHP
父子任务使用不当线程池死锁怎么解决?
在Java多线程编程中,线程池有助于提升性能与资源利用效率,但若父子任务共用同一池,则可能诱发死锁。本文通过一个具体案例剖析此问题:在一个固定大小为2的线程池中,父任务直接调用`outerTask`,而`outerTask`再次使用同一线程池异步调用`innerTask`。理论上,任务应迅速完成,但实际上却超时未完成。经由`jstack`输出的线程调用栈分析发现,线程陷入等待状态,形成“死锁”。原因是子任务需待父任务完成,而父任务则需等待子任务执行完毕以释放线程,从而相互阻塞。此问题在测试环境中不易显现,常在生产环境下高并发时爆发,重启或扩容仅能暂时缓解。
|
存储 监控 算法
实现死锁检测组件
实现死锁检测组件
68 0
|
8月前
|
存储 监控 程序员
线程死锁检测组件逻辑与源码
线程死锁检测组件逻辑与源码
87 2
|
8月前
|
存储
死锁检测组件
死锁检测组件
44 0
|
8月前
|
存储 安全 C语言
死锁检测组件原理及代码实现
死锁检测组件原理及代码实现
|
算法 调度
死锁原因及死锁检测组件的实现
死锁原因及死锁检测组件的实现
138 0
|
安全 Java
锁升级原理
锁升级是指在多线程环境下,当一个线程持有了低级别的锁(如偏向锁或轻量级锁)时,如果有其他线程也要获取这个锁,那么就需要将锁升级为重量级锁。这样可以保证在并发情况下,多个线程之间的互斥访问。
264 1
|
安全 Java 调度
【Java并发编程 五】线程生命周期及状态切换
【Java并发编程 五】线程生命周期及状态切换
103 0
|
关系型数据库 中间件 MySQL
上手全局锁,死锁
上手全局锁,死锁
上手全局锁,死锁

热门文章

最新文章

相关实验场景

更多