面试题答案
一键面试实现思路
- 自定义信号类型:使用
sigaction
函数来定义信号处理函数,并指定要处理的信号。可以选择一个未被系统使用的信号编号(通常大于SIGRTMIN
且小于SIGRTMAX
用于实时信号)。 - 线程间同步通信:一个线程发送信号,另一个或多个线程接收并处理该信号。发送信号使用
pthread_kill
函数,它可以向指定线程发送信号。 - 避免竞态条件:
- 使用互斥锁:在信号处理函数中涉及共享资源访问时,使用互斥锁来保护共享资源,确保同一时间只有一个线程可以访问。
- 信号屏蔽:在关键代码段屏蔽信号,处理完共享资源后再解除屏蔽。可以使用
sigprocmask
函数来实现信号屏蔽和解除屏蔽。
关键代码示例
#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
// 自定义信号编号,使用实时信号
#define CUSTOM_SIGNAL SIGRTMIN
pthread_mutex_t mutex;
int shared_variable = 0;
// 信号处理函数
void signal_handler(int signum) {
pthread_mutex_lock(&mutex);
// 处理共享资源
shared_variable++;
printf("Signal received, shared_variable: %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
}
void* thread_function(void* arg) {
// 屏蔽信号
sigset_t set;
sigemptyset(&set);
sigaddset(&set, CUSTOM_SIGNAL);
pthread_sigmask(SIG_BLOCK, &set, NULL);
// 模拟一些工作
sleep(2);
// 发送信号
pthread_kill(pthread_self(), CUSTOM_SIGNAL);
// 解除信号屏蔽
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
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(CUSTOM_SIGNAL, &sa, NULL);
// 创建线程
pthread_create(&thread, NULL, thread_function, NULL);
// 等待线程结束
pthread_join(thread, NULL);
// 销毁互斥锁
pthread_mutex_destroy(&mutex);
return 0;
}
在上述代码中:
- 自定义信号处理函数:
signal_handler
函数在接收到自定义信号CUSTOM_SIGNAL
时,对共享变量shared_variable
进行操作,并使用互斥锁保护。 - 线程函数:
thread_function
函数中,首先屏蔽信号,进行一些工作后发送信号,最后解除信号屏蔽。 - 主线程:在主线程中,初始化互斥锁,设置信号处理函数,创建并等待线程结束,最后销毁互斥锁。