进程 | 生产者和消费者

本文介绍了操作系统中进程和线程的概念,以及生产者-消费者模型在多线程环境下的应用。通过使用互斥锁和条件变量,实现了生产者和消费者之间的同步,防止缓冲区溢出或空洞。当缓冲区满时,生产者阻塞,消费者运行;反之,消费者阻塞,生产者运行。文章还提及了死锁问题和银行家算法作为死锁预防的策略。

这其实是操作系统上的内容,进程,系统分配资源的最小单位,线程,系统执行指令的最小单位(也可以叫执行任务)
操作系统,充分利用电气特性提升操作任务的性能,同时多进程提升并发执行性能。
现实生活中,生产者–消费者关系。
这是一个很强的一前一后、一前一后……的同步逻辑关系。
说白了,就像流水线。
这其实也是通信的一种,生产者–>缓存区—>消费者
当缓存区为空时,消费者通知生产者快点生产。此时消费者阻塞,生产者在跑。
当缓存区满的时候,生产者通知消费者,缓存区满了,我不能再生产了(生产者),此时生产者阻塞,消费者在跑。
可以通过加锁,实现,生产者生产一块饼干,消费者接着就吃一块饼干。

#include <iostream>
#include <vector>
#include <pthread.h>

const int BUFFER_SIZE = 5;
std::vector<int> buffer;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;

void* producer(void* arg) {
    for (int i = 0; i < 10; ++i) {
        pthread_mutex_lock(&mutex);						//保护线程同步条件变量锁

        while (buffer.size() == BUFFER_SIZE) {
            // 缓冲区已满,等待消费者消费数据	生产者不能再生产数据
            std::cout << "Producer: Buffer is full. Waiting...\n";
            pthread_cond_wait(&_cond, &mutex);			//生产者在等 线程同步条件变量被消费者占用
        }

        buffer.push_back(i);
        std::cout << "Producer: Produced data: " << i << "\n";

        pthread_cond_signal(&_cond); // 唤醒等待的消费者线程 把线程同步条件变量释放,然后消费者可以占用
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

void* consumer(void* arg) {
    for (int i = 0; i < 10; ++i) {
        pthread_mutex_lock(&mutex);

        while (buffer.empty()) {
            // 缓冲区为空,等待生产者生产数据
            std::cout << "Consumer: Buffer is empty. Waiting...\n";
            pthread_cond_wait(&_cond, &mutex);
        }

        int data = buffer.back();
        buffer.pop_back();
        std::cout << "Consumer: Consumed data: " << data << "\n";

        pthread_cond_signal(&_cond); // 唤醒等待的生产者线程
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

int main() {
    pthread_t producerThread, consumerThread;
    pthread_create(&producerThread, NULL, producer, NULL);
    pthread_create(&consumerThread, NULL, consumer, NULL);

    pthread_join(producerThread, NULL);
    pthread_join(consumerThread, NULL);

    return 0;
}

pthread_join(producerThread, NULL);表示阻塞当前的main进程,让进程producerThread去跑
后面还有,哲学家吃饭问题、抽烟问题。
其实,后面还可以延伸到死锁问题,死锁预防(银行家算法),其本质就是按照一定规则推算,当下的所有资源能不能满足所有进程的执行,如果可以,这说明不会存在死锁,否者,会发生死锁。应当解决死锁问题。那么就涉及到如何解决死锁问题。

实验题目: 生产者消费者(综合性实验) 实验环境: C语言编译器 实验内容: ① 由用户指定要产生的进程及其类别,存入进入就绪队列。    ② 调度程序从就绪队列中提取一个就绪进程运行。如果申请的资源被阻塞则进入相应的等待队列,调度程序调度就绪队列中的下一个进程进程运行结束时,会检查对应的等待队列,激活队列中的进程进入就绪队列。运行结束的进程进入over链表。重复这一过程直至就绪队列为空。    ③ 程序询问是否要继续?如果要转直①开始执行,否则退出程序。 实验目的: 通过实验模拟生产者消费者之间的关系,了解并掌握他们之间的关系及其原理。由此增加对进程同步的问题的了解。 实验要求: 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程类型标号、进程系统号、进程状态、进程产品(字符)、进程链指针等等。 系统开辟了一个缓冲区,大小由buffersize指定。 程序中有三个链队列,一个链表。一个就绪队列(ready),两个等待队列:生产者等待队列(producer);消费者队列(consumer)。一个链表(over),用于收集已经运行结束的进程 本程序通过函数模拟信号量的操作。 参考书目: 1)徐甲同等编,计算机操作系统教程,西安电子科技大学出版社 2)Andrew S. Tanenbaum著,陈向群,马红兵译. 现代操作系统(第2版). 机械工业出版社 3)Abranham Silberschatz, Peter Baer Galvin, Greg Gagne著. 郑扣根译. 操作系统概念(第2版). 高等教育出版社 4)张尧学编著. 计算机操作系统教程(第2版)习题解答与实验指导. 清华大学出版社 实验报告要求: (1) 每位同学交一份电子版本的实验报告,上传到202.204.125.21服务器中。 (2) 文件名格式为班级、学号加上个人姓名,例如: 电子04-1-040824101**.doc   表示电子04-1班学号为040824101号的**同学的实验报告。 (3) 实验报告内容的开始处要列出实验的目的,实验环境、实验内容等的说明,报告中要附上程序代码,并对实验过程进行说明。 基本数据结构: PCB* readyhead=NULL, * readytail=NULL; // 就绪队列 PCB* consumerhead=NULL, * consumertail=NULL; // 消费者队列 PCB* producerhead=NULL, * producertail=NULL; // 生产者队列 over=(PCB*)malloc(sizeof(PCB)); // over链表 int productnum=0; //产品数量 int full=0, empty=buffersize; // semaphore char buffer[buffersize]; // 缓冲区 int bufferpoint=0; // 缓冲区指针 struct pcb { /* 定义进程控制块PCB */ int flag; // flag=1 denote producer; flag=2 denote consumer; int numlabel; char product; char state; struct pcb * processlink; …… }; processproc( )--- 给PCB分配内存。产生相应的的进程:输入1为生产者进程;输入2为消费者进程,并把这些进程放入就绪队列中。 waitempty( )--- 如果缓冲区满,该进程进入生产者等待队列;linkqueue(exe,&producertail); // 把就绪队列里的进程放入生产者队列的尾部 void signalempty() bool waitfull() void signalfull() void producerrun() void comsuerrun() void main() { processproc(); element=hasElement(readyhead); while(element){ exe=getq(readyhead,&readytail); printf("进程%d申请运行,它是一个",exe->numlabel); exe->flag==1? printf("生产者\n"):printf("消费者\n"); if(exe->flag==1) producerrun();
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值