面试题答案
一键面试可能出现的问题
- 数据不一致:信号处理函数和主线程或其他线程同时访问并修改共享资源,可能导致数据处于不一致的状态。例如,一个计数器变量在主线程中正在进行累加操作,但信号处理函数同时对其进行读取或修改,可能导致错误的计数值。
- 程序崩溃:由于共享资源的访问冲突,可能导致程序出现段错误等异常情况,最终导致程序崩溃。比如,共享资源是一个指针,信号处理函数和主线程同时对其进行释放操作,就可能引发双重释放错误。
避免信号竞争的方法及代码示例
1. 使用互斥锁(Mutex)
通过互斥锁来保护共享资源,确保在同一时间只有一个线程(包括信号处理函数)能够访问共享资源。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
pthread_mutex_t mutex;
int shared_variable = 0;
void signal_handler(int signum) {
pthread_mutex_lock(&mutex);
// 处理共享资源
shared_variable++;
printf("Signal handler: shared_variable = %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
}
void* thread_function(void* arg) {
while (1) {
pthread_mutex_lock(&mutex);
// 处理共享资源
shared_variable++;
printf("Thread: shared_variable = %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
sleep(1);
}
return NULL;
}
int main() {
pthread_t thread;
struct sigaction sa;
pthread_mutex_init(&mutex, NULL);
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
pthread_create(&thread, NULL, thread_function, NULL);
while (1) {
// 主线程逻辑
sleep(1);
// 发送信号
kill(getpid(), SIGUSR1);
}
pthread_join(thread, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
2. 使用信号量(Semaphore)
信号量可以控制对共享资源的访问数量,同样能避免信号竞争。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>
sem_t semaphore;
int shared_variable = 0;
void signal_handler(int signum) {
sem_wait(&semaphore);
// 处理共享资源
shared_variable++;
printf("Signal handler: shared_variable = %d\n", shared_variable);
sem_post(&semaphore);
}
void* thread_function(void* arg) {
while (1) {
sem_wait(&semaphore);
// 处理共享资源
shared_variable++;
printf("Thread: shared_variable = %d\n", shared_variable);
sem_post(&semaphore);
sleep(1);
}
return NULL;
}
int main() {
pthread_t thread;
struct sigaction sa;
sem_init(&semaphore, 0, 1);
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
pthread_create(&thread, NULL, thread_function, NULL);
while (1) {
// 主线程逻辑
sleep(1);
// 发送信号
kill(getpid(), SIGUSR1);
}
pthread_join(thread, NULL);
sem_destroy(&semaphore);
return 0;
}