面试题答案
一键面试解决同步问题的方法
- 信号量(Semaphore):信号量是一个计数器,用于控制对共享资源的访问。通过获取和释放信号量来控制进程对共享内存的访问,从而保证数据一致性。
- 互斥锁(Mutex):互斥锁本质上是一种特殊的二元信号量(值为0或1),用于保证在同一时刻只有一个进程能够访问共享资源。
- 条件变量(Condition Variable):条件变量通常与互斥锁一起使用,用于线程或进程间的同步。它允许进程在某个条件满足时被唤醒。
- 读写锁(Read - Write Lock):读写锁区分读操作和写操作。允许多个进程同时进行读操作,但只允许一个进程进行写操作,并且在写操作进行时不允许读操作。
使用信号量解决共享内存同步问题的C语言代码示例
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <unistd.h>
#define SHM_SIZE 1024
int main() {
key_t key;
int shmid;
char *shmaddr;
sem_t *semaphore;
// 生成一个唯一的键值
key = ftok(".", 'a');
if (key == -1) {
perror("ftok");
return 1;
}
// 创建共享内存段
shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);
if (shmid == -1) {
perror("shmget");
return 1;
}
// 连接共享内存段到进程地址空间
shmaddr = (char *)shmat(shmid, NULL, 0);
if (shmaddr == (void *)-1) {
perror("shmat");
return 1;
}
// 创建信号量
semaphore = sem_open("/mysemaphore", O_CREAT, 0666, 1);
if (semaphore == SEM_FAILED) {
perror("sem_open");
return 1;
}
// 子进程
if (fork() == 0) {
// 获取信号量
if (sem_wait(semaphore) == -1) {
perror("sem_wait");
return 1;
}
// 子进程写入共享内存
sprintf(shmaddr, "Hello from child process");
printf("Child process has written to shared memory.\n");
// 释放信号量
if (sem_post(semaphore) == -1) {
perror("sem_post");
return 1;
}
} else {
// 父进程等待子进程完成写入
wait(NULL);
// 获取信号量
if (sem_wait(semaphore) == -1) {
perror("sem_wait");
return 1;
}
// 父进程读取共享内存
printf("Parent process reads from shared memory: %s\n", shmaddr);
// 释放信号量
if (sem_post(semaphore) == -1) {
perror("sem_post");
return 1;
}
// 分离共享内存段
if (shmdt(shmaddr) == -1) {
perror("shmdt");
return 1;
}
// 删除共享内存段
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl");
return 1;
}
// 删除信号量
if (sem_close(semaphore) == -1) {
perror("sem_close");
return 1;
}
if (sem_unlink("/mysemaphore") == -1) {
perror("sem_unlink");
return 1;
}
}
return 0;
}
此代码展示了如何使用信号量来保证共享内存数据的一致性。在父子进程间,通过信号量来协调对共享内存的读写操作,避免数据不一致问题。