当线程多了之后,一部分线程做数据处理,一个线程做日志同步,还有做网络的线程及操作数据库的线程,当线程比较多的时候出现死锁的概率是很高的;
使用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发现资源被其他线程占用的时候;