操作系统模拟生产者-消费者问题

@[TOC]生产者-消费者问题

生产者-消费者问题

生产者-消费者问题:
一群生产者在生产消息,并将此消息提供给消费者去消费。它们中间设了具有N个缓存区的缓冲池,生产者每次可将生产的消息放入一个缓存区内,消费者每次可将一个缓存区内的消息拿出来消费。但这个过程有两个条件:任何一方操作一个缓冲区时不能有其它同时对该缓冲区进行操作;只有当缓冲区还有空余,生产者才能生产,只有当缓冲区至少有一个产品,消费者才能从中取出来消费。这里两个条件分别对应了互斥和同步。
在这里插入图片描述
如上图所示便是生产者-消费者模型,它是利用存储中介隔离生产者和消费者的交互,相比直通而言,它的好处在于:不必相互等待,提高运行效率。

实现思路

运用所学的线程互斥锁和条件变量来实现此模型。
对于生产者而言:
(1)先上锁
(2)如果存储中介中元素大于或等于存储最大数量,则不需要生产,则阻塞于此,释放锁;反之,则生产,
(3)在收到可生产条件信号之后,便唤醒进程,判断是否可生产,(可能只需要生产一件,但唤醒了多个线程)
(4)生产结束后,释放锁

对于消费者者而言:
(1)先上锁
(2)如果存储中介中元素小于或等于0,则不能消费,则阻塞于此,释放锁;反之,则消费,
(3)在收到可消费条件信号之后,便唤醒进程,判断是否可消费,(可能只能消费一件,但唤醒了多个线程)
(4)消费结束后,释放锁

实现代码

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>

typedef struct Store{ //存储缓冲区结构体
    char things[10];
    int cnt;
}Store;

Store s;
pthread_mutex_t mutex; //互斥锁类型
pthread_cond_t notfull; //缓冲区未满(可生产)信号
pthread_cond_t notempty;//缓冲区未空(可消费)信号

void *proc(void *arg) { //product 生产
    while(1){
        pthread_mutex_lock(&mutex);  //上锁
        while(s.cnt >= 10) { //必须用while 不能用if
            pthread_cond_wait(&notfull,&mutex); //等待 并释放锁
        }
        char c = rand()%26+'A';
        s.things[s.cnt++] = c;
        size_t i;
        for(i = 0;i < s.cnt;i++) {
            printf("%c ",s.things[i]);
        }
        printf("\n");
        printf("放入:%c\n",c);
        pthread_cond_signal(&notempty); //生产后必定可消费 发出可消费条件信号
        pthread_mutex_unlock(&mutex); // 解锁
        usleep(rand()%100000);
    }
}
 void *cust(void *arg) { //消费
     while(1){
         pthread_mutex_lock(&mutex);//上锁
         while(s.cnt <= 0) {
             pthread_cond_wait(&notempty,&mutex);
         }
         size_t i;
         for(i = 0;i < s.cnt;i++) {
             printf("%c ",s.things[i]);
         }
         printf("\n");
         char c = s.things[--s.cnt];
         printf("取出:%c\n",c);
         pthread_cond_signal(&notfull);//消费后必定可生产 发出可生产信号
         pthread_mutex_unlock(&mutex);//解锁
         usleep(rand()%100000);
     }
 }
 
 int main() {
     srand(time(NULL));
     pthread_t ids[6];
     pthread_mutex_init(&mutex,NULL); // 互斥量初始化
     pthread_cond_init(&notfull,NULL); // 条件变量初始化
     pthread_cond_init(&notempty,NULL);
     size_t i;
     for(i = 0;i < 6;i++) {
         if(i%2 == 0) {
             pthread_create(&ids[i],NULL,proc,NULL);
         }else{
             pthread_create(&ids[i],NULL,cust,NULL);
         }
     }
     getchar();
     return 0;
 }

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
生产者-消费者问题是一个经典的并发问题,描述了两个进程(或线程)之间的同步和通信问题生产者进程负责生产一些物品并将它们放入一个缓冲区中,而消费者进程则从缓冲区中取出物品并将其消耗掉。该问题的关键在于确保生产者消费者不会同时访问缓冲区,以免出现竞态条件和数据不一致的问题。 以下是一个使用信号量来解决生产者-消费者问题的示例代码: ```c++ #include <cstdio> #include <cstdlib> #include <pthread.h> #include <semaphore.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; // 缓冲区 int in = 0; // 生产者放置产品的位置 int out = 0; // 消费者取产品的位置 sem_t empty; // 同步信号量,表示缓冲区中空闲位置的数量 sem_t full; // 同步信号量,表示缓冲区中已有产品的数量 pthread_mutex_t mutex; // 互斥锁,保护对缓冲区的访问 void *producer(void *arg) { for (int i = 0; i < 100; i++) { sem_wait(&empty); pthread_mutex_lock(&mutex); buffer[in] = rand() % 100; printf("Producer produces item %d: %d\n", in, buffer[in]); in = (in + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); sem_post(&full); } } void *consumer(void *arg) { for (int i = 0; i < 100; i++) { sem_wait(&full); pthread_mutex_lock(&mutex); int item = buffer[out]; printf("Consumer consumes item %d: %d\n", out, item); out = (out + 1) % BUFFER_SIZE; pthread_mutex_unlock(&mutex); sem_post(&empty); } } int main() { sem_init(&empty, 0, BUFFER_SIZE); // 初始化 empty 为 BUFFER_SIZE sem_init(&full, 0, 0); // 初始化 full 为 0 pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 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); pthread_mutex_destroy(&mutex); return 0; } ``` 读者-写者问题也是一个经典的并发问题,描述了多个进程(或线程)之间共享一个资源的情况。在读者-写者问题中,资源可以被多个读者同时访问,但只能由一个写者访问。如果一个写者正在访问资源,那么其他所有的读者和写者都必须等待。如果一个读者正在访问资源,那么其他的读者可以同时访问,但写者必须等待所有的读者都访问完毕后才能访问。 以下是一个使用互斥锁和条件变量来解决读者-写者问题的示例代码: ```c++ #include <cstdio> #include <cstdlib> #include <pthread.h> #define READERS_COUNT 5 #define WRITERS_COUNT 3 int read_count = 0; // 当前正在读取资源的读者数量 int resource = 0; // 被读取和写入的共享资源 pthread_mutex_t read_mutex; // 保护 read_count 的互斥锁 pthread_mutex_t write_mutex; // 保护 resource 的互斥锁 pthread_cond_t write_cond; // 写者等待的条件变量 pthread_cond_t read_cond; // 读者等待的条件变量 void *reader(void *arg) { int id = *(int *) arg; while (true) { pthread_mutex_lock(&read_mutex); read_count++; if (read_count == 1) { pthread_mutex_lock(&write_mutex); } pthread_mutex_unlock(&read_mutex); printf("Reader %d reads resource: %d\n", id, resource); pthread_mutex_lock(&read_mutex); read_count--; if (read_count == 0) { pthread_mutex_unlock(&write_mutex); } pthread_mutex_unlock(&read_mutex); sleep(rand() % 3); } } void *writer(void *arg) { int id = *(int *) arg; while (true) { pthread_mutex_lock(&write_mutex); while (read_count > 0) { pthread_cond_wait(&write_cond, &write_mutex); } resource = rand() % 100; printf("Writer %d writes resource: %d\n", id, resource); pthread_cond_broadcast(&read_cond); pthread_mutex_unlock(&write_mutex); sleep(rand() % 3); } } int main() { pthread_mutex_init(&read_mutex, NULL); pthread_mutex_init(&write_mutex, NULL); pthread_cond_init(&read_cond, NULL); pthread_cond_init(&write_cond, NULL); pthread_t readers[READERS_COUNT], writers[WRITERS_COUNT]; int reader_ids[READERS_COUNT], writer_ids[WRITERS_COUNT]; for (int i = 0; i < READERS_COUNT; i++) { reader_ids[i] = i + 1; pthread_create(&readers[i], NULL, reader, &reader_ids[i]); } for (int i = 0; i < WRITERS_COUNT; i++) { writer_ids[i] = i + 1; pthread_create(&writers[i], NULL, writer, &writer_ids[i]); } for (int i = 0; i < READERS_COUNT; i++) { pthread_join(readers[i], NULL); } for (int i = 0; i < WRITERS_COUNT; i++) { pthread_join(writers[i], NULL); } pthread_mutex_destroy(&read_mutex); pthread_mutex_destroy(&write_mutex); pthread_cond_destroy(&read_cond); pthread_cond_destroy(&write_cond); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值