面试题答案
一键面试1. 信号量机制实现进程同步与互斥原理
- 同步:通过信号量来协调进程的执行顺序,使得进程按照预定的顺序依次执行特定的操作。例如,进程 A 需要在进程 B 完成某个操作后才能继续执行,就可以利用信号量来实现这种同步关系。
- 互斥:信号量可被视为一种特殊的二元信号量(取值为 0 或 1),也叫互斥锁。它用于保证在同一时刻只有一个进程能够进入临界区(共享资源访问区域),从而避免多个进程同时访问共享资源导致的数据不一致等问题。
2. 信号量取值变化及对应进程行为举例
假设我们有两个进程 P1 和 P2 共享一个资源,使用信号量 S 来实现互斥访问。信号量 S 的初始值设为 1。
- P1 尝试进入临界区:
- P1 执行
wait(S)
操作,此时 S 的值减 1,变为 0。这表示 P1 成功获取到信号量,进入临界区开始访问共享资源。
- P1 执行
- P2 尝试进入临界区:
- P2 执行
wait(S)
操作,由于 S 当前值为 0,再减 1 会小于 0,P2 会被阻塞,放入与信号量 S 相关的等待队列中,等待信号量的值变为可获取状态。
- P2 执行
- P1 离开临界区:
- P1 执行
signal(S)
操作,S 的值加 1,变为 1。这意味着 P1 释放了信号量,同时系统会从等待队列中唤醒一个进程(假设唤醒 P2)。
- P1 执行
- P2 被唤醒后进入临界区:
- 被唤醒的 P2 再次执行
wait(S)
操作,S 的值减 1 变为 0,P2 成功进入临界区访问共享资源。
- 被唤醒的 P2 再次执行
代码示例(以 C 语言结合 POSIX 信号量为例):
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
sem_t mutex;
int shared_variable = 0;
void* increment(void* arg) {
sem_wait(&mutex);
shared_variable++;
printf("Incrementing: %d\n", shared_variable);
sem_post(&mutex);
return NULL;
}
void* decrement(void* arg) {
sem_wait(&mutex);
shared_variable--;
printf("Decrementing: %d\n", shared_variable);
sem_post(&mutex);
return NULL;
}
int main() {
pthread_t tid1, tid2;
sem_init(&mutex, 0, 1);
pthread_create(&tid1, NULL, increment, NULL);
pthread_create(&tid2, NULL, decrement, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
sem_destroy(&mutex);
return 0;
}
在上述代码中,sem_t mutex
定义了一个信号量,初始值为 1。sem_wait(&mutex)
相当于 wait(S)
操作,sem_post(&mutex)
相当于 signal(S)
操作。两个线程 increment
和 decrement
通过这个信号量实现对共享变量 shared_variable
的互斥访问。