经典进程同步问题C语言
时间: 2023-08-10 09:12:22 浏览: 192
经典的进程同步问题通常包括生产者-消费者问题、读者-写者问题和哲学家就餐问题等。这里以生产者-消费者问题为例,简单介绍一下如何在 C 语言中实现进程同步。
生产者-消费者问题是指多个进程共享同一个缓冲区,其中生产者进程向缓冲区中写入数据,而消费者进程则从缓冲区中读取数据。为了避免竞争条件和死锁等问题,需要使用同步机制来保证进程之间的协调工作。
使用信号量可以实现进程同步。信号量是一个计数器,用于控制对共享资源的访问。在 C 语言中,我们可以使用 POSIX 信号量库来创建和使用信号量。
下面是一个简单的生产者-消费者问题的代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
sem_t empty; // 缓冲区空闲信号量
sem_t full; // 缓冲区满信号量
pthread_mutex_t mutex; // 互斥锁
void *producer(void *arg)
{
int item;
while (1) {
item = rand() % 100; // 生产一个随机数
sem_wait(&empty); // 当缓冲区空间为 0 时等待
pthread_mutex_lock(&mutex);
buffer[in] = item;
in = (in + 1) % BUFFER_SIZE; // 循环缓冲区
printf("Producer produced item %d\n", item);
pthread_mutex_unlock(&mutex);
sem_post(&full); // 增加缓冲区中的项目数
}
pthread_exit(NULL);
}
void *consumer(void *arg)
{
int item;
while (1) {
sem_wait(&full); // 当缓冲区中没有项目时等待
pthread_mutex_lock(&mutex);
item = buffer[out];
out = (out + 1) % BUFFER_SIZE; // 循环缓冲区
printf("Consumer consumed item %d\n", item);
pthread_mutex_unlock(&mutex);
sem_post(&empty); // 增加缓冲区的空闲空间
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
pthread_t producer_thread, consumer_thread;
sem_init(&empty, 0, BUFFER_SIZE); // 初始化信号量
sem_init(&full, 0, 0);
pthread_mutex_init(&mutex, NULL);
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);
pthread_mutex_destroy(&mutex);
return 0;
}
```
在这个示例中,我们使用了两个信号量 `empty` 和 `full` 来控制缓冲区的空闲空间和项目数。当 `empty` 为 0 时,表示缓冲区已满,生产者需要等待;当 `full` 为 0 时,表示缓冲区没有项目,消费者需要等待。使用互斥锁 `mutex` 来保护共享资源的访问,避免竞争条件。
当生产者生成一个随机数时,将其写入缓冲区,同时增加 `in` 指针,表示缓冲区中的项目数增加了一个。当消费者读取缓冲区中的项目时,将其存储到 `item` 中,并将 `out` 指针增加,表示缓冲区中的项目数减少了一个。
上述代码中,生产者和消费者都是无限循环运行的,可以使用 `pthread_cancel()` 函数来终止它们的运行。此外,还需要注意的是,在使用信号量等同步机制时,不要忘记释放已经申请的资源,否则可能会导致死锁等问题。
阅读全文