C++11 操作系统原理 生产者消费者实验

    xiaoxiao2025-08-22  6

    看见网上给的生产者消费者的例子是基于windows API下的编程,不但脱离了操作系统底层设计的初衷,还更依赖于平台。

    故使用C++13标准,重写了生产者消费者模拟程序。

    首先,由于C++没有信号量机制,利用互斥锁实现一个信号量类。代码如下:

    Semaphore.h

    /* 一个信号量类(来自网络) */ #pragma once #include<mutex> class Semaphore { public: Semaphore(unsigned long count = 0) : m_count(count) {} Semaphore(const Semaphore&) = delete; Semaphore& operator=(const Semaphore&) = delete; void Signal(){ { std::unique_lock<std::mutex> lock(m_mutex); ++m_count; } m_cv_uptr.notify_one(); } void Wait(){ std::unique_lock<std::mutex> lock(m_mutex); while (m_count == 0) { // 这里可能会虚假唤醒 m_cv_uptr.wait(lock); } --m_count; } private: std::mutex m_mutex; std::condition_variable m_cv_uptr; unsigned long m_count; };

    其次,定义一个BufferSimulation类,来实现缓冲区的模拟

    【BufferSimulation.h】

    /* 使用C++11标准 写了一个消费者生产者——缓冲区类 作者:吕翔宇 E-mail:630056108@qq.com 2019年5月26日 版权所有 ALL RIGHTS RESERVED! */ #pragma warning(disable:4996) #pragma once #include<iostream> #include<vector> #include<string> #include<mutex> #include<thread> #include"Semaphore.h" class BufferSimulation{ public: BufferSimulation(int producerNum, int consumerNum, int bufferSize, int delayTime, bool stepMode); ~BufferSimulation(); private: std::vector<std::string> buffer; // 缓冲区 std::vector<std::thread> producers; // 生产者们 std::vector<std::thread> consumers; // 消费者们 int producerNum, consumerNum, bufferSize, delayTime; std::mutex t_mutex; // 用于线程间的互斥 Semaphore bufferSemaphore; // 缓冲区信号量 int produce_ptr; // 生产者放置位置 int consume_ptr; // 消费者使用位置 bool stop; int count = 0; // 记录当前货物编号 std::thread stepModeThread; // 步过进程 public: void printBuffer(int loc); private: void produce(int id); // 生产程序 void consume(int id); // 消费程序 void stepMode(); // 单步模式 public: bool canStop; };

    其实现代码如下

    【BufferSimulation.cpp】

    /* 使用C++11标准 写了一个消费者生产者——缓冲区类 作者:吕翔宇 E-mail:630056108@qq.com 2019年5月26日 版权所有 ALL RIGHTS RESERVED! */ #include "BufferSimulation.h" BufferSimulation::BufferSimulation(int producerNum, int consumerNum, int bufferSize, int delayTime, bool stepMode) : producerNum(producerNum), consumerNum(consumerNum), bufferSize(bufferSize), delayTime(delayTime), stop(false), bufferSemaphore(bufferSize), // 信号量与缓冲区大小一致 buffer(bufferSize), canStop(false) { if (stepMode) stepModeThread = std::thread(&BufferSimulation::stepMode, this); else canStop = true; for (int i = 0; i < producerNum; i++) { producers.push_back(std::thread(&BufferSimulation::produce, this,i)); std::cout << "创建了一个生产者者进程!" <<"进程号为:"<< producers[i].get_id()<< std::endl; } // 创建消费者 for (int j = 0; j < consumerNum; j++) { consumers.push_back(std::thread(&BufferSimulation::consume, this,j)); std::cout << "创建了一个消费者进程!" << "进程号为:" << consumers[j].get_id() << std::endl; } } void BufferSimulation::stepMode() { canStop = false; bool pass = true; while (true) { _sleep(300); if (pass) { t_mutex.lock(); pass = false; } std::cout << "\n指令 1.停止运行 2.调到下一秒 3.打印缓冲区\n请输入:"; int tmp; std::cin >> tmp; if (tmp == 1) { stop = true; t_mutex.unlock(); _sleep(delayTime); canStop = true; return; }else { if (tmp == 2) { t_mutex.unlock(); _sleep(1000); pass = true; } else { if (tmp == 3) { printBuffer(-1); } else { std::cout << "指令无效\n"; } } } } } BufferSimulation::~BufferSimulation() { stop = true; for (int i = 0; i < producerNum; i++) { producers[i].detach(); } for (int i = 0; i < consumerNum; i++) { std::cout << "销毁消费者" << std::endl; consumers[i].detach(); } system("pause"); } void BufferSimulation::printBuffer(int loc) { std::cout << "————————————" << std::endl; std::cout << "缓冲区号\t\t内容\n"; for (int i = 0; i < bufferSize; i++) { if (i != loc) { std::cout << i << "\t\t\t" << buffer[i] << "\n"; } else { std::cout << i << "\t\t\t" << buffer[i] << "\t<--"<<"\n"; } } std::cout << "————————————" << std::endl; } void BufferSimulation::produce(int id) { while (true) { if (stop) { std::cout << "\n生产者 " << id << " 退出\n"; break; } _sleep(delayTime); bufferSemaphore.Wait(); // 等待有地方放 t_mutex.lock(); if (stop) { bufferSemaphore.Signal(); t_mutex.unlock(); std::cout << "\n生产者 " << id << " 退出\n"; break; } buffer[produce_ptr] = std::to_string(count); printBuffer(produce_ptr); produce_ptr = (produce_ptr + 1) % bufferSize; std::cout << std::this_thread::get_id()<<" "<< id << "号进程(生产者)生产:" << count << std::endl; count++; t_mutex.unlock(); } } void BufferSimulation::consume(int id) { while (true) { if (stop) { std::cout << "\n消费者 " << id << " 退出\n"; break; } _sleep(delayTime); bufferSemaphore.Signal(); // 等待有东西用 t_mutex.lock(); if (stop) { bufferSemaphore.Wait(); t_mutex.unlock(); std::cout << "\n消费者 " << id << " 退出\n"; break; } std::string product = buffer[consume_ptr]; buffer[consume_ptr] = ""; printBuffer(consume_ptr); consume_ptr = (consume_ptr + 1) % bufferSize; std::cout << std::this_thread::get_id() << " " << id << "号进程(消费者)消费:" << product << std::endl; t_mutex.unlock(); } }

    【main.cpp】

    /* 基于C++11模拟生产者-消费者,缓冲队列的实现 作者:吕翔宇 E-Mail:630056108@qq.com 2019年5月26日 版权所有 ALL RIGHTS RESERVED! */ #include"BufferSimulation.h" int main(int argc, char ** argv) { int producerNum; int consumerNum; int bufferSize; int delayTime; bool stepMode; std::cout << "生产者数:"; std::cin >> producerNum; std::cout << "消费者数:"; std::cin >> consumerNum; std::cout << "缓冲区大小:"; std::cin >> bufferSize; std::cout << "间隔大小(毫秒):"; std::cin >> delayTime; std::cout << "是否步过模式(0:自动运行,1:步过模式):"; std::cin >> stepMode; BufferSimulation simulation(producerNum, consumerNum, bufferSize, delayTime, stepMode); while (!simulation.canStop) _sleep(1000); system("pause"); return 0; }

    下面在时间间隔模式下进行演示:

    参数如下:

     

     

     

    打印缓冲区得到:

     

    停止运行:

     

     

    自动模式下的演示略过,动态的不易演示。

     

     

    最新回复(0)