首页后端开发ASP.NETC++解决方法:多线程同步经典案例之生产者消费者问题

C++解决方法:多线程同步经典案例之生产者消费者问题

时间2024-01-30 22:52:03发布访客分类ASP.NET浏览196
导读:收集整理的这篇文章主要介绍了C++解决方法:多线程同步经典案例之生产者消费者问题,觉得挺不错的,现在分享给大家,也给大家做个参考。抄自维基百科 :生产者消费者问题(英语:PRoducer-consumer problem),也称有限缓冲问题...
收集整理的这篇文章主要介绍了C++解决方法:多线程同步经典案例之生产者消费者问题,觉得挺不错的,现在分享给大家,也给大家做个参考。抄自维基百科 :

生产者消费者问题(英语:PRoducer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。

本文用一个ITemRepository类表示产品仓库,其中包含一个数组和两个坐标表示的环形队列、一个std::mutex成员、用来保证每次只被一个线程读写操作 (为了保证打印出来的消息是一行一行的,在它空闲的时候也借用的这个互斥量╮(╯▽╰)╭)、两个std::condition_VARiable表示队列不满和不空的状态,进而保证生产的时候不满,消耗的时候不空。

#pragma once#include chrono>
    //std::chrono#include mutex>
    //std::mutex,std::unique_lock,std::lock_Guard#include thread>
    //std::thread#include condition_variable>
    //std::condition_variable#include iostream>
    //std::cout,std::endl#include map>
//std::mapnamespace MyProducerToConsumer {
        static const int gRepositorySize = 10;
    //total size of the repository    static const int gItemNum = 97;
    //number of products to produce    std::mutex produce_mtx, consume_mtx;
    //mutex for all the producer thread or consumer thread    std::mapstd::thread::id, int>
     threadPErformance;
//records of every thread's producing/consuming number    struct ItemRepository {
    //repository class        int m_ItemBuffer[gRepositorySize];
    //Repository itself (as a circular queue)        int m_ProducePos;
    //rear position of circular queue        int m_ConsumePos;
    //head position of circular queue        std::mutex m_mtx;
    //mutex for operating the repository        std::condition_variable m_RepoUnfull;
    //indicating that this repository is unfull(then producers can produce items)        std::condition_variable m_RepoUnempty;
//indicating that this repository is unempty(then consumers can produce items)    }
    gItemRepo;
    void Produceitem(ItemRepository *ir, int item) {
            std::unique_lock std::mutex>
    ulk(ir->
    m_mtx);
            while ((ir->
    m_ProducePos + 1) % gRepositorySize == ir->
m_ConsumePos) {
    //full(spare one slot for indicating)            std::cout  "Reposity is full. Waiting for consumers..."  std::endl;
                ir->
    m_RepoUnfull.wait(ulk);
//unlocking ulk and waiting for unfull condition        }
            //when unfull        ir->
    m_ItemBuffer[ir->
    m_ProducePos++] = item;
    //procude and shift        std::cout  "Item No."  item  " produced successfully by "            std::this_thread::get_id()"!"  std::endl;
            threadPerformance[std::this_thread::get_id()]++;
            if (ir->
    m_ProducePos == gRepositorySize)//loop            ir->
    m_ProducePos = 0;
            ir->
    m_RepoUnempty.notify_all();
    //item produced, so it's unempty;
 notify all consumers    }
    int ConsumeItem(ItemRepository *ir) {
            std::unique_lockstd::mutex>
    ulk(ir->
    m_mtx);
            while (ir->
    m_ConsumePos == ir->
m_ProducePos) {
    //empty            std::cout  "Repository is empty.Waiting for producing..."  std::endl;
                ir->
    m_RepoUnempty.wait(ulk);
        }
            int item = ir->
    m_ItemBuffer[ir->
    m_ConsumePos++];
            std::cout  "Item No."  item  " consumed successfully by "            std::this_thread::get_id()"!"  std::endl;
            threadPerformance[std::this_thread::get_id()]++;
            if (ir->
    m_ConsumePos == gRepositorySize)            ir->
    m_ConsumePos = 0;
            ir->
    m_RepoUnfull.notify_all();
    //item consumed, so it's unempty;
     notify all consumers        return item;
    }
    void ProducerThread() {
            static int produced = 0;
//static variable to indicate the number of produced items        while (1) {
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
    //sleep long enough in case it runs too fast for other threads to procude            std::lock_guardstd::mutex>
    lck(produce_mtx);
    //auto unlock when break            produced++;
                if (produced >
     gItemNum)break;
                gItemRepo.m_mtx.lock();
                std::cout  "Producing item No."  produced  "..."  std::endl;
                gItemRepo.m_mtx.unlock();
                ProduceItem(&
    gItemRepo, produced);
        }
            gItemRepo.m_mtx.lock();
            std::cout  "Producer thread "  std::this_thread::get_id()             " exited."  std::endl;
            gItemRepo.m_mtx.unlock();
    }
    void ConsumerThread() {
            static int consumed = 0;
        while (1) {
                std::this_thread::sleep_for(std::chrono::milliseconds(10));
                std::lock_guardstd::mutex>
    lck(consume_mtx);
                consumed++;
                if (consumed >
     gItemNum)break;
                gItemRepo.m_mtx.lock();
                std::cout  "Consuming item available..."  std::endl;
                gItemRepo.m_mtx.unlock();
                ConsumeItem(&
    gItemRepo);
        }
            gItemRepo.m_mtx.lock();
            std::cout  "Consumer thread "  std::this_thread::get_id()             " exited."  std::endl;
            gItemRepo.m_mtx.unlock();
    }
    void InitItemRepository(ItemRepository* ir) {
            ir->
    m_ConsumePos = 0;
            ir->
    m_ProducePos = 0;
    }
    void Run() {
            InitItemRepository(&
    gItemRepo);
            std::thread thdConsume[11];
            std::thread thdProduce[11];
            for (auto&
     t : thdConsume)t = std::thread(ConsumerThread);
            for (auto&
     t : thdProduce)t = std::thread(ProducerThread);
            for (auto&
     t : thdConsume)t.join();
            for (auto&
     t : thdProduce)t.join();
            for (auto&
     iter : threadPerformance)cout  iter.First  ":"  iter.second  endl;
    }
}
    

相关文章:

关于java生产者与消费者的实例详解

java多线程之并发协作生产者消费者设计模式

以上就是C++解决方法:多线程同步经典案例之生产者消费者问题的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

上一篇: Microsoft C++ 语言扩展:try-ex...下一篇:第六章C++:函数基础与应用猜你在找的ASP.NET相关文章 C# 一些面试试题的实例教程2022-05-16.NET 6开发TodoList应用之请求日志组件HttpLogging介绍2022-04-16.NET 6中间件Http Logging使用介绍2022-04-16gojs一些实用的高级用法2022-04-16.NET6开发TodoList应用之实现查询排序2022-04-16.NET6开发TodoList应用之实现数据塑形2022-04-16.NET微服务架构CI/CD自动打包镜像2022-04-16Asp.Net Core 使用Monaco Editor 实现代码编辑器功能2022-04-16.NET微服务架构CI/CD自动构建Jenkins+Gitee2022-04-16.Net Core微服务网关Ocelot集成Consul2022-04-16 其他相关热搜词更多phpjavapython程序员loadpost-format-gallery

若转载请注明出处: C++解决方法:多线程同步经典案例之生产者消费者问题
本文地址: https://pptw.com/jishu/593144.html
Microsoft C++ 语言扩展:try-except 语句结构化异常 手把手带你使用node开发一款图集打包工具

游客 回复需填写必要信息