用信号量解决经典同步问题(生产者消费者问题,哲学家进餐问题,读者写者问题c
时间: 2023-11-15 11:04:10 浏览: 116
C语言信号量同步与互斥生产者消费者互斥锁读写者问题哲学家就餐问题课程设计
5星 · 资源好评率100%
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;
}
```
阅读全文