MST

星途 面试题库

面试题:C++多进程编程的同步与互斥

假设你正在使用C++开发一个多进程应用程序,多个进程需要访问共享资源。请描述如何使用信号量来实现进程间的同步与互斥,避免资源竞争。请用代码示例展示如何在C++中初始化、获取和释放信号量,并且说明信号量的值在不同场景下应如何设置。
44.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

信号量实现进程间同步与互斥原理

信号量(Semaphore)是一个整型变量,通过一个计数器来控制对共享资源的访问。当计数器的值大于0时,表示有可用资源,进程可以获取信号量(计数器减1)来访问资源;当计数器的值为0时,表示资源已被占用,进程需要等待信号量释放(计数器加1)。

C++ 代码示例

在C++中,可以使用POSIX信号量来实现进程间同步与互斥。以下是一个简单的示例代码,展示如何初始化、获取和释放信号量:

#include <iostream>
#include <semaphore.h>
#include <unistd.h>
#include <sys/wait.h>

const int sharedResource = 0; // 共享资源

int main() {
    sem_t* semaphore;
    // 初始化信号量,值为1表示初始时有一个可用资源(用于互斥)
    semaphore = sem_open("/my_semaphore", O_CREAT, 0666, 1); 

    if (semaphore == SEM_FAILED) {
        std::cerr << "Failed to create semaphore" << std::endl;
        return 1;
    }

    pid_t pid = fork();

    if (pid == -1) {
        std::cerr << "Fork failed" << std::endl;
        sem_close(semaphore);
        sem_unlink("/my_semaphore");
        return 1;
    } else if (pid == 0) { // 子进程
        // 获取信号量
        if (sem_wait(semaphore) == 0) { 
            std::cout << "Child process entered critical section" << std::endl;
            // 访问共享资源
            std::cout << "Child process accessing shared resource: " << sharedResource << std::endl;
            // 释放信号量
            sem_post(semaphore); 
            std::cout << "Child process left critical section" << std::endl;
        } else {
            std::cerr << "Child process failed to acquire semaphore" << std::endl;
        }
    } else { // 父进程
        // 获取信号量
        if (sem_wait(semaphore) == 0) { 
            std::cout << "Parent process entered critical section" << std::endl;
            // 访问共享资源
            std::cout << "Parent process accessing shared resource: " << sharedResource << std::endl;
            // 释放信号量
            sem_post(semaphore); 
            std::cout << "Parent process left critical section" << std::endl;
            wait(nullptr); // 等待子进程结束
        } else {
            std::cerr << "Parent process failed to acquire semaphore" << std::endl;
        }
    }

    // 关闭并删除信号量
    sem_close(semaphore); 
    sem_unlink("/my_semaphore"); 

    return 0;
}

信号量值的设置

  1. 互斥场景
    • 信号量初始值设为1。这意味着同一时间只有一个进程可以获取信号量,进入临界区访问共享资源,从而实现互斥。在上述代码中,sem_open("/my_semaphore", O_CREAT, 0666, 1); 将信号量初始值设为1。
  2. 同步场景(如生产者 - 消费者模型)
    • 资源可用信号量:如果有N个初始可用资源,信号量初始值设为N。例如,在生产者 - 消费者模型中,如果缓冲区初始有5个空位,那么表示缓冲区空位的信号量初始值设为5。消费者进程在从缓冲区取数据前获取该信号量(信号量值减1),生产者进程向缓冲区写数据后释放该信号量(信号量值加1)。
    • 资源占用信号量:如果要表示缓冲区已占用的数量,初始值设为0。生产者进程向缓冲区写数据前获取该信号量(因为初始无数据,需等待消费者取数据后才有空位),消费者进程从缓冲区取数据后释放该信号量。