MST

星途 面试题库

面试题:C语言解除信号屏蔽后如何处理信号竞争问题

假设在一个多线程的C程序中,解除了对某个信号的屏蔽,此时可能会出现信号竞争的情况,比如信号处理函数与主线程或其他线程同时访问共享资源。请描述可能出现的问题,并给出至少两种避免信号竞争的方法及对应的C代码示例。
48.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

可能出现的问题

  1. 数据不一致:信号处理函数和主线程或其他线程同时访问并修改共享资源,可能导致数据处于不一致的状态。例如,一个计数器变量在主线程中正在进行累加操作,但信号处理函数同时对其进行读取或修改,可能导致错误的计数值。
  2. 程序崩溃:由于共享资源的访问冲突,可能导致程序出现段错误等异常情况,最终导致程序崩溃。比如,共享资源是一个指针,信号处理函数和主线程同时对其进行释放操作,就可能引发双重释放错误。

避免信号竞争的方法及代码示例

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;
}