用信号量解决经典同步问题(生产者消费者问题,哲学家进餐问题,读者写者问题c
时间: 2023-11-15 10:04:10 浏览: 131
1. 生产者消费者问题
生产者消费者问题是一种经典的同步问题,其中生产者线程将数据添加到共享缓冲区中,而消费者线程从该缓冲区中获取数据。为了避免竞争条件和死锁,我们需要使用信号量来解决这个问题。
使用两个信号量,一个用于表示缓冲区是否为空,另一个用于表示缓冲区是否已满。当缓冲区已满时,生产者将等待,直到缓冲区不再满。当缓冲区为空时,消费者将等待,直到缓冲区中有更多数据。
以下是用信号量解决生产者消费者问题的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
sem_t empty, full;
int in = 0, out = 0;
void *producer(void *arg) {
int item;
while (1) {
item = rand() % 100;
sem_wait(&empty);
buffer[in] = item;
printf("Producer produced item %d at %d\n", item, in);
in = (in + 1) % BUFFER_SIZE;
sem_post(&full);
}
}
void *consumer(void *arg) {
int item;
while (1) {
sem_wait(&full);
item = buffer[out];
printf("Consumer consumed item %d at %d\n", item, out);
out = (out + 1) % BUFFER_SIZE;
sem_post(&empty);
}
}
int main() {
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
pthread_t producer_thread, consumer_thread;
pthread_create(&producer_thread, NULL, producer, NULL);
pthread_create(&consumer_thread, NULL, consumer, NULL);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
sem_destroy(&empty);
sem_destroy(&full);
return 0;
}
```
2. 哲学家进餐问题
哲学家进餐问题是一个经典的同步问题,其中有五个哲学家围坐在圆桌旁,每个哲学家需要交替地思考和进餐。他们之间共享五个叉子,每个哲学家需要两个叉子才能进餐。
使用信号量来解决哲学家进餐问题。每个叉子都有一个信号量,当哲学家想要使用叉子时,他必须先获取左边的叉子,然后获取右边的叉子。当哲学家用完叉子时,他将释放两个叉子的信号量。
以下是用信号量解决哲学家进餐问题的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_PHILOSOPHERS 5
sem_t forks[NUM_PHILOSOPHERS];
pthread_mutex_t mutex;
void *philosopher(void *arg) {
int id = *(int *)arg;
int left = id;
int right = (id + 1) % NUM_PHILOSOPHERS;
while (1) {
// think
printf("Philosopher %d is thinking\n", id);
sleep(rand() % 3);
// pick up forks
pthread_mutex_lock(&mutex);
sem_wait(&forks[left]);
sem_wait(&forks[right]);
pthread_mutex_unlock(&mutex);
printf("Philosopher %d is eating\n", id);
sleep(rand() % 3);
// put down forks
sem_post(&forks[left]);
sem_post(&forks[right]);
}
}
int main() {
int ids[NUM_PHILOSOPHERS];
pthread_t philosophers[NUM_PHILOSOPHERS];
pthread_mutex_init(&mutex, NULL);
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
sem_init(&forks[i], 0, 1);
ids[i] = i;
pthread_create(&philosophers[i], NULL, philosopher, &ids[i]);
}
for (int i = 0; i < NUM_PHILOSOPHERS; i++) {
pthread_join(philosophers[i], NULL);
sem_destroy(&forks[i]);
}
pthread_mutex_destroy(&mutex);
return 0;
}
```
3. 读者写者问题
读者写者问题是一个经典的同步问题,其中有多个读者和写者同时访问共享资源。多个读者可以同时读取共享资源,但是只有一个写者可以写入共享资源。当写者正在写入共享资源时,其他读者和写者都需要等待。
使用信号量来解决读者写者问题。使用两个信号量,一个用于表示共享资源是否正在被写入,另一个用于表示读者数量。当写者正在写入共享资源时,所有请求访问共享资源的读者和写者都需要等待。当有读者正在读取共享资源时,所有写者都需要等待。当没有写者正在写入共享资源并且没有读者正在读取共享资源时,写者可以开始写入共享资源。
以下是用信号量解决读者写者问题的示例代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define NUM_READERS 5
#define NUM_WRITERS 2
int shared_resource = 0;
sem_t resource_mutex, read_mutex;
int num_readers = 0;
void *reader(void *arg) {
while (1) {
sem_wait(&read_mutex);
num_readers++;
if (num_readers == 1) {
sem_wait(&resource_mutex);
}
sem_post(&read_mutex);
printf("Reader read value %d\n", shared_resource);
sleep(rand() % 3);
sem_wait(&read_mutex);
num_readers--;
if (num_readers == 0) {
sem_post(&resource_mutex);
}
sem_post(&read_mutex);
}
}
void *writer(void *arg) {
while (1) {
sem_wait(&resource_mutex);
printf("Writer wrote value %d\n", ++shared_resource);
sleep(rand() % 3);
sem_post(&resource_mutex);
}
}
int main() {
pthread_t readers[NUM_READERS], writers[NUM_WRITERS];
sem_init(&resource_mutex, 0, 1);
sem_init(&read_mutex, 0, 1);
for (int i = 0; i < NUM_READERS; i++) {
pthread_create(&readers[i], NULL, reader, NULL);
}
for (int i = 0; i < NUM_WRITERS; i++) {
pthread_create(&writers[i], NULL, writer, NULL);
}
for (int i = 0; i < NUM_READERS; i++) {
pthread_join(readers[i], NULL);
}
for (int i = 0; i < NUM_WRITERS; i++) {
pthread_join(writers[i], NULL);
}
sem_destroy(&resource_mutex);
sem_destroy(&read_mutex);
return 0;
}
```
阅读全文