使用C语言实现模拟生产者 消费者进程实现同步与互斥操作,并加注释
时间: 2024-01-07 08:02:34 浏览: 83
下面是使用C语言实现的生产者消费者问题,并使用信号量实现同步与互斥操作的代码。代码中使用了POSIX标准的信号量库。
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int in = 0, out = 0;
sem_t empty, full;
pthread_mutex_t mutex;
void *producer(void *arg)
{
int item;
while (1) {
item = rand() % 1000; // 生成随机数
sem_wait(&empty); // 等待空缓冲区
pthread_mutex_lock(&mutex);
buffer[in] = item; // 将随机数添加到缓冲区中
in = (in + 1) % BUFFER_SIZE;
printf("Producing item %d\n", item);
pthread_mutex_unlock(&mutex);
sem_post(&full); // 增加满缓冲区信号量
sleep(1);
}
}
void *consumer(void *arg)
{
int item;
while (1) {
sem_wait(&full); // 等待有数据可消费
pthread_mutex_lock(&mutex);
item = buffer[out]; // 从缓冲区中取出数据
out = (out + 1) % BUFFER_SIZE;
printf("Consuming item %d\n", item);
pthread_mutex_unlock(&mutex);
sem_post(&empty); // 增加空缓冲区信号量
sleep(1);
}
}
int main()
{
pthread_t tid1, tid2;
// 初始化信号量和互斥锁
sem_init(&empty, 0, BUFFER_SIZE);
sem_init(&full, 0, 0);
pthread_mutex_init(&mutex, NULL);
// 创建并启动生产者和消费者线程
pthread_create(&tid1, NULL, producer, NULL);
pthread_create(&tid2, NULL, consumer, NULL);
// 等待线程结束
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
// 销毁信号量和互斥锁
sem_destroy(&empty);
sem_destroy(&full);
pthread_mutex_destroy(&mutex);
return 0;
}
```
在上面的代码中,我们使用了一个大小为10的缓冲区作为生产者和消费者之间的共享资源。生产者线程会生成一个随机数,并将其添加到缓冲区中,而消费者线程则从缓冲区中取出一个随机数进行消费。为了实现线程间的同步和互斥,我们使用了POSIX标准的信号量库和互斥锁。
在程序开始时,我们通过调用sem_init函数和pthread_mutex_init函数来初始化信号量和互斥锁。empty信号量初始化为BUFFER_SIZE,表示缓冲区中有BUFFER_SIZE个空闲位置可以用于生产者线程添加随机数。full信号量初始化为0,表示缓冲区中没有可用于消费的数据。互斥锁初始化为NULL,表示使用默认的属性。
在生产者线程中,我们首先使用sem_wait函数来等待空闲缓冲区的出现。如果缓冲区已经满了,那么该函数会阻塞线程,等待信号量变为非0。然后,我们使用pthread_mutex_lock函数来获取互斥锁,保证在缓冲区中添加随机数时不会出现竞争和冲突。接着,我们将随机数添加到缓冲区中,更新in指针,打印出当前生产的数值。最后,我们使用pthread_mutex_unlock函数释放互斥锁,并使用sem_post函数增加full信号量,表示缓冲区中的可消费数据数量增加了一个。
在消费者线程中,我们首先使用sem_wait函数来等待有数据可消费。如果缓冲区为空,那么该函数会阻塞线程,等待信号量变为非0。然后,我们使用pthread_mutex_lock函数来获取互斥锁,保证在缓冲区中取出随机数时不会出现竞争和冲突。接着,我们从缓冲区中取出数据,更新out指针,打印出当前消费的数值。最后,我们使用pthread_mutex_unlock函数释放互斥锁,并使用sem_post函数增加empty信号量,表示缓冲区中的空闲位置数量增加了一个。
在程序结束时,我们通过调用sem_destroy函数和pthread_mutex_destroy函数来销毁信号量和互斥锁。
阅读全文