关于多线程与信号使用锁的问题

在多线程程序中使用信号处理程序的时候,一定要注意,信号处理函数中一定不能使用锁,信号处理函数应该尽可能的简单,最好只是对于一些标志位的赋值,然后再其他线程中,对标志位进行轮询查看,在线程中处理更多的逻辑。先上程序

#include <stdio.h>
#include <pthread.h>
#include <signal.h>

#define THREAD_NUM 10
pthread_t tid[10];
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void sig_handler(int sig)
{
	pthread_mutex_lock(&mutex);
	printf("sig_handler\n");
	pthread_mutex_unlock(&mutex);
}

void *thread_handler(void *arg)
{
	while (1)
	{
		pthread_mutex_lock(&mutex);
		printf("%ld thread_handler\n", pthread_self());
		usleep(1000);
		pthread_mutex_unlock(&mutex);
	}
}
void *t_handler(void *arg)
{
	while (1)
	{
		printf("%ld thread_handler\n", pthread_self());
		usleep(1000);
	}
}
int main()
{
	signal(SIGINT, sig_handler);
 	int i;
	for (i = 0; i < THREAD_NUM; i++)
	{
		pthread_create(&tid[i], NULL, thread_handler, NULL);
	}
	pthread_t t;
	pthread_create(&t, NULL, t_handler, NULL);

	for (i = 0; i < THREAD_NUM; i++)
	{
		pthread_join(tid[i], NULL);
	}

	return 0;	
}

程序很简单,就是一个信号处理,还有十个线程,而且信号处理函数和这十个线程都使用同一个锁。在编译完运行后, 不断的使用CTRL+C,给程序发中断,最后程序运行会卡住,即使没有加锁的线程也会因为被信号中断,而信号中断函数被锁住而无法继续运行。下面为pstack看到的堆栈信息:

Thread 12 (Thread 0x7f7f47a6a700 (LWP 15083)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 11 (Thread 0x7f7f47069700 (LWP 15084)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 10 (Thread 0x7f7f46668700 (LWP 15085)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 9 (Thread 0x7f7f45c67700 (LWP 15086)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 8 (Thread 0x7f7f45265700 (LWP 15087)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 7 (Thread 0x7f7f44864700 (LWP 15088)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 6 (Thread 0x7f7f43e63700 (LWP 15089)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 5 (Thread 0x7f7f43462700 (LWP 15090)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 4 (Thread 0x7f7f42a61700 (LWP 15091)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a778acb8d in nanosleep () from /lib64/libc.so.6
#6  0x0000003a778e1d64 in usleep () from /lib64/libc.so.6
#7  0x0000000000400801 in thread_handler ()
#8  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#9  0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 3 (Thread 0x7f7f42060700 (LWP 15092)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c0e052 in __lll_lock_wait () from /lib64/libpthread.so.0
#6  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#7  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#8  0x00000000004007d5 in thread_handler ()
#9  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#10 0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 2 (Thread 0x7f7f4165f700 (LWP 15093)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a778acb8d in nanosleep () from /lib64/libc.so.6
#6  0x0000003a778e1d64 in usleep () from /lib64/libc.so.6
#7  0x0000000000400845 in t_handler ()
#8  0x0000003a77c07851 in start_thread () from /lib64/libpthread.so.0
#9  0x0000003a778e890d in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7f7f47a6c700 (LWP 15082)):
#0  0x0000003a77c0e054 in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x0000003a77c09388 in _L_lock_854 () from /lib64/libpthread.so.0
#2  0x0000003a77c09257 in pthread_mutex_lock () from /lib64/libpthread.so.0
#3  0x00000000004007a9 in sig_handler ()
#4  <signal handler called>
#5  0x0000003a77c080ab in pthread_join () from /lib64/libpthread.so.0
#6  0x00000000004008d5 in main ()

可以看到,线程中会存在<signal handler called>,也就是说线程被信号中断了,而信号中断了的线程,可能正好获得了锁,正在运行printf或者usleep程序,还没释放锁,这时候信号来了,将该线程中断,去处理信号处理函数,信号处理函数sig_handler也需要获得该锁,结果就导致了信号处理函数获取不了锁,而被信号中断的线程也无法继续运行,程序就被卡死了。

先随便写写,后续可能再补充

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux多线程信号量是一种用于控制多个线程并发访问共享资源的机制。它可以确保同一时间只有一个线程能够访问共享资源,从而避免了多个线程同时访问共享资源而导致的数据竞争和不一致性问题。在Linux中,信号量通常使用semaphore机制来实现,它提供了一组原子操作,包括P操作和V操作,用于对信号量进行加和解操作。通过使用信号量,可以有效地保证多线程程序的正确性和可靠性。 ### 回答2: Linux多线程信号量是一种保护机制,用于控制多个线程同时访问共享资源的方式。在Linux环境下,信号量一般指的是二进制信号量或计数信号量。 二进制信号量可以看做是一个线程在访问共享资源时必须获得这个,否则就会被阻塞等待释放。在Linux中,使用sem_init()函数创建二进制信号量,sem_wait()函数获取,sem_post()函数释放。在获取时,如果已被占用,则该线程会被阻塞,直到释放。 计数信号量可以表示一类资源的数量,线程使用一定数量的资源时需要获取相应数量的计数信号量。在Linux中,使用sem_init()函数创建计数信号量,sem_wait()函数获取信号量,sem_post()函数释放信号量。在获取计数信号量时,如果当前数量不足,则该线程会被阻塞,直到资源数量足够。 Linux多线程信号量的使用可以避免多个线程同时对共享资源操作的问题,提高系统并发度和稳定性。但是需要注意的是,使用信号量并不能解决所有并发问题,还需要结合其他同步机制,如互斥、条件变量等,才能构建完整的并发控制方案。 ### 回答3: Linux多线程信号量是一种线程同步和互斥的机制,它是由Linux内核提供的一种机制,用于控制多个线程并发访问共享资源。信号量在多线程编程中被广泛使用,用于控制线程的访问和操作共享资源的顺序。 信号量的值表示着可以同时访问该共享资源的线程数量,当某个线程想要访问资源时,需要先获取信号量的,如果此时信号量的值为0则线程需要等待,直到其他线程释放信号量的后才能获得进入临界区。 Linux中实现了两种类型的信号量:二元信号量和计数信号量。二元信号量只有两种状态,可以表示互斥访问,即同一时间只有一个线程能访问该资源;计数信号量可以表示多个线程同时访问该资源。 在多线程编程中,线程之间的访问共享资源会涉及到许多同步和互斥的问题使用信号量可以很好的解决这些问题。当多个线程需要资源时,信号量可以对线程进行调度,当有资源可用时不会浪费时间,同时避免了过度竞争。 使用信号量还可以避免出现死的情况,当多个线程同时申请资源时,如果无法获取到,就会进入等待状态,当某个线程获取到了就会释放资源,其他线程就能继续执行,从而避免了死的情况。 总之,Linux多线程信号量是线程同步和互斥的重要机制,可以解决线程之间的竞争问题,保证程序运行的正确性和正常性,使多线程编程变得更加高效、安全、可靠。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值