MST

星途 面试题库

面试题:C语言多进程服务器模型的同步与互斥

在Linux C语言多进程服务器模型中,不同进程可能会访问共享资源。请详细阐述如何使用信号量或互斥锁来实现进程间的同步与互斥,以保证数据的一致性和完整性。举例说明在高并发场景下可能出现的同步问题及解决方案。
17.7万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

1. 使用信号量实现进程间同步与互斥

信号量本质上是一个计数器,它通过控制访问共享资源的进程数量来实现同步与互斥。

初始化信号量

#include <semaphore.h>
sem_t semaphore;
// 初始化信号量为1,代表同一时间只允许一个进程访问共享资源
sem_init(&semaphore, 0, 1); 

这里sem_init函数第一个参数是指向sem_t类型变量的指针,第二个参数表示信号量是否在多个进程间共享(0表示不共享,1表示共享),第三个参数是信号量的初始值。

获取信号量(进入临界区)

sem_wait(&semaphore); 

sem_wait函数会将信号量的值减1,如果信号量的值为0,那么这个函数会阻塞,直到信号量的值大于0。

释放信号量(离开临界区)

sem_post(&semaphore); 

sem_post函数会将信号量的值加1,唤醒因等待该信号量而阻塞的进程。

2. 使用互斥锁实现进程间同步与互斥

互斥锁本质上是特殊的二元信号量(值为0或1),用于保护共享资源,保证同一时间只有一个进程能够访问共享资源。

初始化互斥锁

#include <pthread.h>
pthread_mutex_t mutex;
// 初始化互斥锁
pthread_mutex_init(&mutex, NULL); 

pthread_mutex_init函数第一个参数是指向pthread_mutex_t类型变量的指针,第二个参数用于设置互斥锁的属性(一般为NULL)。

锁定互斥锁(进入临界区)

pthread_mutex_lock(&mutex); 

如果互斥锁当前处于解锁状态,pthread_mutex_lock函数会将其锁定并返回;如果互斥锁已被锁定,该函数会阻塞直到互斥锁被解锁。

解锁互斥锁(离开临界区)

pthread_mutex_unlock(&mutex); 

pthread_mutex_unlock函数会将互斥锁解锁,唤醒因等待该互斥锁而阻塞的进程。

3. 高并发场景下可能出现的同步问题及解决方案

同步问题 - 竞态条件

在高并发场景下,多个进程可能同时访问和修改共享资源,导致数据不一致。例如,多个进程同时对一个共享的计数器进行加1操作:

// 共享计数器
int counter = 0; 

// 进程1
void *process1(void *arg) {
    int temp = counter;
    temp++;
    counter = temp;
    return NULL;
}

// 进程2
void *process2(void *arg) {
    int temp = counter;
    temp++;
    counter = temp;
    return NULL;
}

如果进程1和进程2同时执行上述代码,可能会出现竞态条件,导致最终的counter值比预期少1。

解决方案

使用信号量或互斥锁来解决竞态条件问题。以互斥锁为例:

#include <pthread.h>
pthread_mutex_t mutex;
int counter = 0; 

// 进程1
void *process1(void *arg) {
    pthread_mutex_lock(&mutex);
    int temp = counter;
    temp++;
    counter = temp;
    pthread_mutex_unlock(&mutex);
    return NULL;
}

// 进程2
void *process2(void *arg) {
    pthread_mutex_lock(&mutex);
    int temp = counter;
    temp++;
    counter = temp;
    pthread_mutex_unlock(&mutex);
    return NULL;
}

通过在访问共享资源counter前后分别锁定和解锁互斥锁,保证同一时间只有一个进程能够访问和修改counter,从而避免竞态条件。