生产者消费者c语言代码_生产者消费者问题、父子进程、信号量(IPC机制):代码分享...
时间: 2023-09-19 11:05:56 浏览: 202
### 回答1:
下面是一个基于信号量实现的生产者消费者问题的C语言代码:
```
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFFER_SIZE 5 // 缓冲区大小
int buffer[BUFFER_SIZE]; // 缓冲区数组
int in = 0; // 生产者放置产品的位置
int out = 0; // 消费者取产品的位置
sem_t empty_sem; // 同步信号量,表示缓冲区中空余的数量
sem_t full_sem; // 同步信号量,表示缓冲区中已经存放的产品数量
pthread_mutex_t mutex; // 互斥锁,保证同一时刻只有一个线程访问缓冲区
void *producer(void *arg);
void *consumer(void *arg);
int main()
{
pthread_t tid1, tid2;
// 初始化信号量和互斥锁
sem_init(&empty_sem, 0, BUFFER_SIZE);
sem_init(&full_sem, 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);
sem_destroy(&full_sem);
pthread_mutex_destroy(&mutex);
return 0;
}
void *producer(void *arg)
{
int i, item;
for (i = 0; i < 10; i++) {
// 生成一个产品
item = rand() % 100;
// 等待缓冲区中空闲的位置
sem_wait(&empty_sem);
// 获取缓冲区互斥锁
pthread_mutex_lock(&mutex);
// 将产品放入缓冲区
buffer[in] = item;
printf("Producer put item %d at %d\n", item, in);
in = (in + 1) % BUFFER_SIZE;
// 释放缓冲区互斥锁
pthread_mutex_unlock(&mutex);
// 发送信号,表示缓冲区中已经有一个产品
sem_post(&full_sem);
// 休眠一段时间
sleep(rand() % 3);
}
pthread_exit(NULL);
}
void *consumer(void *arg)
{
int i, item;
for (i = 0; i < 10; i++) {
// 等待缓冲区中有产品
sem_wait(&full_sem);
// 获取缓冲区互斥锁
pthread_mutex_lock(&mutex);
// 从缓冲区中取出一个产品
item = buffer[out];
printf("Consumer get item %d from %d\n", item, out);
out = (out + 1) % BUFFER_SIZE;
// 释放缓冲区互斥锁
pthread_mutex_unlock(&mutex);
// 发送信号,表示缓冲区中空闲的位置增加了一个
sem_post(&empty_sem);
// 休眠一段时间
sleep(rand() % 3);
}
pthread_exit(NULL);
}
```
这个程序定义了一个缓冲区数组,一个生产者和一个消费者。生产者不断生成随机数,并将它们放入缓冲区中,消费者不断从缓冲区中取出随机数并打印出来。缓冲区的大小为5,程序运行10次后结束。在程序中使用了信号量和互斥锁来保证线程之间的同步和互斥。
### 回答2:
生产者消费者问题是经典的同步问题,通常用于说明多进程/多线程之间的协作关系。下面是一个使用C语言实现的生产者消费者问题的代码分享:
```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 buffer_index = 0; // 缓冲区索引
sem_t full, empty; // 计数信号量
// 生产者线程
void *producer(void *id) {
int producer_id = *((int *)id);
while (1) {
int item = rand() % 100; // 产生一个随机数作为生产的物品
sem_wait(&empty); // 等待缓冲区有空位置可以放入
sem_wait(&mutex); // 上锁,防止多个生产者同时操作缓冲区
buffer[buffer_index] = item; // 将物品放入缓冲区
printf("Producer %d produced item %d\n", producer_id, item);
buffer_index++;
sem_post(&mutex); // 解锁
sem_post(&full); // 增加一个物品到缓冲区,表示有物品可以被消费
}
pthread_exit(NULL);
}
// 消费者线程
void *consumer(void *id) {
int consumer_id = *((int *)id);
while (1) {
sem_wait(&full); // 等待缓冲区有物品可以消费
sem_wait(&mutex); // 上锁,防止多个消费者同时操作缓冲区
int item = buffer[--buffer_index]; // 从缓冲区取出物品
printf("Consumer %d consumed item %d\n", consumer_id, item);
sem_post(&mutex); // 解锁
sem_post(&empty); // 增加一个空位置到缓冲区,表示有空位置可以放入物品
sleep(1); // 模拟消费时间
}
pthread_exit(NULL);
}
int main() {
sem_init(&mutex, 0, 1); // 初始化互斥信号量
sem_init(&full, 0, 0); // 初始化满的信号量为0
sem_init(&empty, 0, BUFFER_SIZE); // 初始化空的信号量为缓冲区大小
pthread_t producer_thread, consumer_thread;
int producer_id = 1, consumer_id = 1;
pthread_create(&producer_thread, NULL, producer, (void *)&producer_id);
pthread_create(&consumer_thread, NULL, consumer, (void *)&consumer_id);
pthread_join(producer_thread, NULL);
pthread_join(consumer_thread, NULL);
sem_destroy(&mutex);
sem_destroy(&full);
sem_destroy(&empty);
return 0;
}
```
以上是一个基于父子进程以及信号量实现的生产者消费者问题的代码分享。在代码中,使用了两个线程分别代表生产者和消费者,通过互斥信号量mutex和计数信号量full、empty实现线程间的同步和互斥操作。
### 回答3:
生产者消费者问题是一种经典的多线程同步问题。在生产者消费者问题中,有两种角色:生产者和消费者。生产者负责生产产品,消费者负责消费产品。这两种角色通过共享的缓冲区进行交互。
以下是一个使用C语言编写的基于父子进程和信号量机制的生产者消费者问题的代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define BUFFER_SIZE 5
#define NUM_PRODUCERS 2
#define NUM_CONSUMERS 2
typedef struct {
int buffer[BUFFER_SIZE];
int in;
int out;
} Buffer;
Buffer sharedBuffer;
union semun {
int val;
struct semid_ds *buf;
unsigned short int *array;
};
void produce(int item) {
sharedBuffer.buffer[sharedBuffer.in] = item;
sharedBuffer.in = (sharedBuffer.in + 1) % BUFFER_SIZE;
}
int consume() {
int item = sharedBuffer.buffer[sharedBuffer.out];
sharedBuffer.out = (sharedBuffer.out + 1) % BUFFER_SIZE;
return item;
}
void producer(int semid) {
int i;
for (i = 0; i < NUM_PRODUCERS; i++) {
sleep(rand() % 3); // 模拟生产过程
semctl(semid, 0, -1); // P操作,申请临界区资源
int item = rand() % 100;
produce(item);
printf("Producer %d produced item: %d\n", getpid(), item);
semctl(semid, 0, 1); // V操作,释放临界区资源
}
exit(0);
}
void consumer(int semid) {
int i;
for (i = 0; i < NUM_CONSUMERS; i++) {
sleep(rand() % 3); // 模拟消费过程
semctl(semid, 0, -1); // P操作,申请临界区资源
int item = consume();
printf("Consumer %d consumed item: %d\n", getpid(), item);
semctl(semid, 0, 1); // V操作,释放临界区资源
}
exit(0);
}
int main() {
int pid;
int semid;
srand(time(NULL));
semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT); // 创建一个信号量集
union semun arg;
arg.val = 1;
semctl(semid, 0, SETVAL, arg); // 初始化信号量
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed\n");
return 1;
} else if (pid > 0) { // 父进程作为生产者
producer(semid);
} else { // 子进程作为消费者
consumer(semid);
}
return 0;
}
```
在代码中,定义了一个缓冲区结构体`Buffer`来存储生产者和消费者共享的缓冲区。`produce`函数用于将产品放入缓冲区,`consume`函数用于从缓冲区中取出产品。
`producer`函数和`consumer`函数分别表示生产者进程和消费者进程的代码逻辑。在这里,我们使用`semget`函数创建了一个信号量集,通过`semctl`函数对信号量进行P操作(申请临界区资源)和V操作(释放临界区资源)。
在`main`函数中,使用`fork`函数创建了一个子进程,父进程作为生产者,子进程作为消费者。
以上是一个简单的生产者消费者问题的C语言代码示例,通过父子进程和信号量机制实现了多线程的同步。
阅读全文