多线程中,信号在哪个线程中处理是不确定的,可能被任意一个线程处理
下边的代码可以验证该结论,多次Ctrl+c,会被不同的线程捕获此信号,并处理,最终每个线程死锁,阻塞在等待锁的状态
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t lock;
// 信号处理函数
void sigint_handler(int signum) {
printf("Received SIGINT signal, %ld\n",pthread_self());
printf("lock line %d\n",__LINE__);
pthread_mutex_lock(&lock);
//usleep(100);
pthread_mutex_unlock(&lock);
printf("unlock line %d\n",__LINE__);
}
// 线程函数
void* thread_func(void* arg) {
while (1) {
printf("thread process, %ld\n",pthread_self());
usleep(100000);
}
return NULL;
}
int main() {
signal(SIGINT, sigint_handler); // 注册SIGINT信号的处理函数
printf("main process, %ld\n",pthread_self());
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread_func, NULL); // 创建一个新线程
pthread_create(&thread2, NULL, thread_func, NULL); // 创建一个新线程
while(1)
{
printf("lock line %d\n",__LINE__);
pthread_mutex_lock(&lock);
usleep(100000); //如果在这个时间段触发中断,就会出现死锁
pthread_mutex_unlock(&lock);
printf("unlock line %d\n",__LINE__);
}
pthread_join(thread1, NULL); // 等待新线程退出
pthread_join(thread2, NULL); // 等待新线程退出
return 0;
}
结果:
main process, 139693373089600
thread process, 139693364594432
lock line 34
thread process, 139693356201728
thread process, 139693364594432
unlock line 38
lock line 34
thread process, 139693356201728
thread process, 139693364594432
unlock line 38
lock line 34
thread process, 139693356201728
^CReceived SIGINT signal, 139693373089600
lock line 10
thread process, 139693364594432
thread process, 139693356201728
thread process, 139693364594432
thread process, 139693364594432
thread process, 139693356201728
thread process, 139693364594432
thread process, 139693356201728
^CReceived SIGINT signal, 139693364594432
lock line 10
thread process, 139693356201728
thread process, 139693356201728
thread process, 139693356201728
thread process, 139693356201728
thread process, 139693356201728
thread process, 139693356201728
thread process, 139693356201728
^CReceived SIGINT signal, 139693356201728
lock line 10
^C^C^C
分析:先主线程usleep(100000);期间 触发中断sigint_handler,从而导致死锁,然后其它线程中触发中断。因此在中断响应函数中使用锁要注意