C++多线程:使用std::condition_variable实现多生产者-多消费者模型示例

C++多线程:使用std::condition_variable实现多生产者-多消费者模型示例

贺志国

示例代码如下:

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <functional>
#include <iomanip>
#include <iostream>
#include <mutex>
#include <queue>
#include <sstream>
#include <thread>
#include <vector>

using namespace std::literals::chrono_literals;

struct CustomOut : public std::stringstream {
 public:
  ~CustomOut() {
    std::lock_guard<std::mutex> lock(cout_mutex_);
    std::cout << rdbuf();
  }

 private:
  static std::mutex cout_mutex_;
};
std::mutex CustomOut::cout_mutex_;

class MultiProducerConsumer {
 public:
  MultiProducerConsumer() = default;
  ~MultiProducerConsumer() = default;

 public:
  void Stop() { production_stopped_.store(true); }

  void Produce(size_t id, size_t items, size_t stock) {
    for (size_t i = 0; i < items; ++i) {
      {
        std::unique_lock<std::mutex> lock(queue_mutex_);
        go_produce_cond_.wait(
            lock, [this, stock] { return product_queue_.size() < stock; });
        product_queue_.push(id * 100 + i);
        CustomOut() << "   Produce " << id << " --> item " << std::setw(3)
                    << product_queue_.back() << '\n';
      }
      go_consume_cond_.notify_all();
      std::this_thread::sleep_for(90ms);
    }
    CustomOut() << "EXIT: Produce " << id << '\n';
  }

  void Consume(size_t id) {
    while (!production_stopped_.load() || !product_queue_.empty()) {
      {
        std::unique_lock<std::mutex> lock(queue_mutex_);
        if (go_consume_cond_.wait_for(
                lock, 1s, [this] { return !product_queue_.empty(); })) {
          CustomOut() << "        item " << std::setw(3)
                      << product_queue_.front() << " --> Consume " << id
                      << '\n';
          product_queue_.pop();
          lock.unlock();
          go_produce_cond_.notify_all();
        }
      }
      std::this_thread::sleep_for(130ms);
    }

    CustomOut() << "EXIT: Consume " << id << "\n";
  }

 private:
  std::atomic<bool> production_stopped_{false};

  std::mutex queue_mutex_;
  std::queue<size_t> product_queue_;
  std::condition_variable go_produce_cond_;
  std::condition_variable go_consume_cond_;
};

int main() {
  std::vector<std::thread> producers;
  std::vector<std::thread> consumers;
  MultiProducerConsumer multi_producer_consumer;
  auto producer = std::bind(&MultiProducerConsumer::Produce,
                            &multi_producer_consumer, std::placeholders::_1,
                            std::placeholders::_2, std::placeholders::_3);

  auto consumer = std::bind(&MultiProducerConsumer::Consume,
                            &multi_producer_consumer, std::placeholders::_1);

  for (size_t i = 0; i < 3; ++i) {
    producers.emplace_back(producer, i, 15, 5);
  }
  for (size_t i = 0; i < 5; ++i) {
    consumers.emplace_back(consumer, i);
  }
  for (auto &t : producers) {
    t.join();
  }

  // `t.join()` in `consumers` blocks the current thread until the thread 't'
  // finishes its execution. The stop instruction should be generated before
  // `t.join()` in `consumers`
  multi_producer_consumer.Stop();
  for (auto &t : consumers) {
    t.join();
  }

  return 0;
}

CMake构建文件如下:

cmake_minimum_required(VERSION 3.0.0)
project(multi_producer_consumer VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 14)

add_executable(${PROJECT_NAME} ${PROJECT_NAME}.cpp)

find_package(Threads REQUIRED)
target_link_libraries(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT})

include(CTest)
enable_testing()
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

运行结果如下:

 ./multi_producer_consumer 
   Produce 2 --> item 200
        item 200 --> Consume 2
   Produce 1 --> item 100
        item 100 --> Consume 0
   Produce 0 --> item   0
        item   0 --> Consume 4
   Produce 2 --> item 201
        item 201 --> Consume 3
   Produce 1 --> item 101
        item 101 --> Consume 1
   Produce 0 --> item   1
        item   1 --> Consume 2
   Produce 2 --> item 202
        item 202 --> Consume 0
   Produce 1 --> item 102
        item 102 --> Consume 4
   Produce 0 --> item   2
        item   2 --> Consume 3
   Produce 2 --> item 203
   Produce 1 --> item 103
        item 203 --> Consume 1
        item 103 --> Consume 2
   Produce 0 --> item   3
        item   3 --> Consume 4
   Produce 2 --> item 204
        item 204 --> Consume 3
   Produce 1 --> item 104
        item 104 --> Consume 0
   Produce 0 --> item   4
        item   4 --> Consume 1
   Produce 2 --> item 205
   Produce 1 --> item 105
        item 205 --> Consume 2
        item 105 --> Consume 4
   Produce 0 --> item   5
        item   5 --> Consume 3
   Produce 2 --> item 206
   Produce 1 --> item 106
        item 206 --> Consume 0
   Produce 0 --> item   6
        item 106 --> Consume 1
        item   6 --> Consume 4
   Produce 2 --> item 207
        item 207 --> Consume 3
   Produce 1 --> item 107
        item 107 --> Consume 2
   Produce 0 --> item   7
        item   7 --> Consume 0
   Produce 2 --> item 208
   Produce 1 --> item 108
        item 208 --> Consume 4
        item 108 --> Consume 1
   Produce 0 --> item   8
        item   8 --> Consume 3
   Produce 2 --> item 209
   Produce 1 --> item 109
   Produce 0 --> item   9
        item 209 --> Consume 0
        item 109 --> Consume 2
        item   9 --> Consume 4
   Produce 2 --> item 210
        item 210 --> Consume 3
   Produce 1 --> item 110
        item 110 --> Consume 1
   Produce 0 --> item  10
        item  10 --> Consume 0
   Produce 2 --> item 211
   Produce 1 --> item 111
   Produce 0 --> item  11
        item 211 --> Consume 2
        item 111 --> Consume 4
        item  11 --> Consume 3
   Produce 2 --> item 212
   Produce 1 --> item 112
        item 212 --> Consume 1
   Produce 0 --> item  12
        item 112 --> Consume 0
        item  12 --> Consume 2
   Produce 2 --> item 213
   Produce 1 --> item 113
        item 213 --> Consume 4
   Produce 0 --> item  13
        item 113 --> Consume 3
        item  13 --> Consume 1
   Produce 2 --> item 214
   Produce 1 --> item 114
        item 214 --> Consume 2
        item 114 --> Consume 0
   Produce 0 --> item  14
        item  14 --> Consume 4
EXIT: Produce 1
EXIT: Produce 2
EXIT: Produce 0
EXIT: Consume 2
EXIT: Consume 0
EXIT: Consume 4
EXIT: Consume 3
EXIT: Consume 1
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值