MST

星途 面试题库

面试题:C语言中Linux信号量在多线程环境下的同步问题

假设你正在编写一个多线程C程序,使用Linux信号量来实现线程间的同步。线程A负责读取数据到缓冲区,线程B从缓冲区读取数据进行处理。请描述如何使用信号量来确保数据的正确读写,避免竞争条件,并写出关键代码片段(不要求完整程序)。
19.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 信号量设计思路

    • 使用两个信号量,一个用于表示缓冲区是否有数据可读(设为data_available),初始值为0。
    • 另一个用于表示缓冲区是否可写(设为buffer_empty),初始值为1。
  2. 关键代码片段

#include <semaphore.h>
#include <pthread.h>

// 定义信号量
sem_t data_available;
sem_t buffer_empty;

// 缓冲区
int buffer;

// 线程A:读取数据到缓冲区
void* threadA(void* arg) {
    while (1) {
        // 等待缓冲区可写
        sem_wait(&buffer_empty);
        // 读取数据到缓冲区
        buffer = get_data();
        // 通知缓冲区有数据可读
        sem_post(&data_available);
    }
    return NULL;
}

// 线程B:从缓冲区读取数据进行处理
void* threadB(void* arg) {
    while (1) {
        // 等待缓冲区有数据可读
        sem_wait(&data_available);
        // 从缓冲区读取数据
        int data = buffer;
        // 通知缓冲区可写
        sem_post(&buffer_empty);
        // 处理数据
        process_data(data);
    }
    return NULL;
}

在上述代码中:

  • sem_wait函数用于等待信号量的值大于0,然后将其值减1。如果信号量的值为0,则线程会阻塞,直到信号量的值变为大于0。
  • sem_post函数用于将信号量的值加1,唤醒可能阻塞在sem_wait上的线程。
  • get_dataprocess_data是假设的函数,分别用于获取数据和处理数据。在实际应用中需要根据具体需求实现。

程序初始化时,需要初始化这两个信号量:

int main() {
    sem_init(&data_available, 0, 0);
    sem_init(&buffer_empty, 0, 1);

    pthread_t tidA, tidB;
    pthread_create(&tidA, NULL, threadA, NULL);
    pthread_create(&tidB, NULL, threadB, NULL);

    pthread_join(tidA, NULL);
    pthread_join(tidB, NULL);

    sem_destroy(&data_available);
    sem_destroy(&buffer_empty);

    return 0;
}

sem_init函数用于初始化信号量,第一个参数为信号量指针,第二个参数表示信号量是否在进程间共享(0表示不共享,用于线程间同步),第三个参数为信号量的初始值。sem_destroy函数用于销毁信号量,在程序结束时需要调用。pthread_create用于创建线程,pthread_join用于等待线程结束。