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

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

贺志国

示例代码如下:

#include <atomic>
#include <condition_variable>
#include <functional>
#include <future>
#include <iostream>
#include <queue>

using namespace std::literals::chrono_literals;

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

 public:
  void Stop() {
    std::cout << "is_stop_.is_lock_free() = " << is_stop_.is_lock_free()
              << '\n';
    is_stop_.store(true);
    task_cond_.notify_one();
  }

  void Produce(size_t items) {
    for (size_t i = 0; i < items; ++i) {
      std::this_thread::sleep_for(100ms);
      {
        std::lock_guard<std::mutex> lk(task_mutex_);
        task_queue_.emplace(i);
      }
      task_cond_.notify_one();
    }

    // is_stop_.store(true);
    // task_cond_.notify_one();
  }

  void Consume() {
    std::unique_lock<std::mutex> lock(task_mutex_);
    while (!is_stop_.load()) {
      task_cond_.wait(
          lock, [this] { return !task_queue_.empty() || is_stop_.load(); });

      while (!task_queue_.empty()) {
        std::cout << "Got " << task_queue_.front() << " from queue.\n";
        task_queue_.pop();
      }
    }
  }

 private:
  std::atomic<bool> is_stop_{false};
  std::queue<size_t> task_queue_;
  std::mutex task_mutex_;
  std::condition_variable task_cond_;
};

int main() {
  ProducerConsumer producer_consumer;

  auto producer = std::async(std::launch::async, &ProducerConsumer::Produce,
                             &producer_consumer, 10);
  auto consumer = std::async(std::launch::async, &ProducerConsumer::Consume,
                             &producer_consumer);
  producer.wait();
  // `consumer.wait()` blocks the current thread until the thread `consumer`
  // finishes its execution. The stop instruction should be generated before
  // `consumer.wait()`
  producer_consumer.Stop();
  consumer.wait();

  std::cout << "Finished!\n";

  return 0;
}

另一种实现方式的代码如下,大家可根据需要挑选具体的实现方式:

#include <atomic>
#include <condition_variable>
#include <functional>
#include <iostream>
#include <queue>
#include <thread>
#include <tuple>

using namespace std::literals::chrono_literals;

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

 public:
  void Stop() {
    std::cout << "is_stop_.is_lock_free() = " << is_stop_.is_lock_free()
              << '\n';
    is_stop_.store(true);
    task_cond_.notify_one();
  }

  void Produce(size_t items) {
    for (size_t i = 0; i < items; ++i) {
      std::this_thread::sleep_for(100ms);

      {
        std::lock_guard<std::mutex> lk(task_mutex_);
        task_queue_.emplace(i);
      }
      task_cond_.notify_one();
    }
  }

  void Consume() {
    while (!is_stop_.load()) {
      std::unique_lock<std::mutex> lock(task_mutex_);
      task_cond_.wait(
          lock, [this] { return !task_queue_.empty() || is_stop_.load(); });

      while (!task_queue_.empty()) {
        std::cout << "Got " << task_queue_.front() << " from queue.\n";
        task_queue_.pop();
      }
    }
  }

 private:
  std::atomic<bool> is_stop_{false};
  std::queue<size_t> task_queue_;
  std::mutex task_mutex_;
  std::condition_variable task_cond_;
};

int main() {
  ProducerConsumer producer_consumer;
  std::thread t1(&ProducerConsumer::Produce, &producer_consumer, 10);
  std::thread t2(&ProducerConsumer::Consume, &producer_consumer);
  t1.join();
  // `t2.join()` blocks the current thread until the thread `t2` finishes its
  // execution. The stop instruction should be generated before `t2.join()`
  producer_consumer.Stop();
  t2.join();

  std::cout << "Finished!\n";

  return 0;
}

CMake构建文件如下:

cmake_minimum_required(VERSION 3.0.0)
project(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)

运行结果如下:

 ./producer_consumer 
Got 0 from queue.
Got 1 from queue.
Got 2 from queue.
Got 3 from queue.
Got 4 from queue.
Got 5 from queue.
Got 6 from queue.
Got 7 from queue.
Got 8 from queue.
Got 9 from queue.
is_stop_.is_lock_free() = 1
Finished!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值