面试题答案
一键面试可能出现死锁的场景
在多线程环境下,当多个线程以不同顺序获取多个互斥锁时,就可能出现死锁。例如,线程A获取互斥锁1,然后尝试获取互斥锁2;而线程B获取互斥锁2,然后尝试获取互斥锁1。如果这两个操作同时进行,就会导致死锁。
代码示例
#include <pthread.h>
#include <stdio.h>
// 定义两个互斥锁
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void* thread_function1(void* arg) {
// 线程1获取mutex1
pthread_mutex_lock(&mutex1);
printf("Thread 1 has locked mutex1\n");
// 线程1尝试获取mutex2
pthread_mutex_lock(&mutex2);
printf("Thread 1 has locked mutex2\n");
// 解锁操作(这里不会执行到,因为死锁了)
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
void* thread_function2(void* arg) {
// 线程2获取mutex2
pthread_mutex_lock(&mutex2);
printf("Thread 2 has locked mutex2\n");
// 线程2尝试获取mutex1
pthread_mutex_lock(&mutex1);
printf("Thread 2 has locked mutex1\n");
// 解锁操作(这里不会执行到,因为死锁了)
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
return NULL;
}
分析
在上述代码中,thread_function1
先获取mutex1
,再获取mutex2
;而thread_function2
先获取mutex2
,再获取mutex1
。如果这两个线程同时运行,就可能出现线程1持有mutex1
,线程2持有mutex2
,然后双方都在等待对方持有的锁,从而导致死锁。
避免死锁的方法
- 按顺序获取锁:所有线程都按照相同的顺序获取互斥锁。
- 使用超时机制:在获取锁时设置一个超时时间,如果在规定时间内没有获取到锁,则放弃并释放已获取的锁。
按顺序获取锁的代码示例
#include <pthread.h>
#include <stdio.h>
// 定义两个互斥锁
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void* thread_function1(void* arg) {
// 线程1按顺序获取mutex1和mutex2
pthread_mutex_lock(&mutex1);
printf("Thread 1 has locked mutex1\n");
pthread_mutex_lock(&mutex2);
printf("Thread 1 has locked mutex2\n");
// 解锁操作
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
void* thread_function2(void* arg) {
// 线程2也按顺序获取mutex1和mutex2
pthread_mutex_lock(&mutex1);
printf("Thread 2 has locked mutex1\n");
pthread_mutex_lock(&mutex2);
printf("Thread 2 has locked mutex2\n");
// 解锁操作
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
分析
在这个改进的代码中,thread_function1
和thread_function2
都按照先获取mutex1
,再获取mutex2
的顺序进行操作。这样就避免了死锁的发生,因为不会出现一个线程持有mutex2
等待mutex1
,而另一个线程持有mutex1
等待mutex2
的情况。