您现在的位置是:首页 > 正文

多线程编程-- 线程安全的queue II

2024-02-01 00:50:24阅读 2

上一篇文章中使用std::mutex 和 条件变量 std::condition_variable 实现了一个线程安全的队列。

这个队列是没有边界的, 也就是允许插入无限多的元素的,事实上这是不可能的, 当元素过多时候,插入元素会失效。这是很危险的一种行为。

下面来实现一个有边界的线程安全的队列 BoundedBlockingQueue

template <typename T>
class BoundedBlockingQueue {
  NOCOPY_CLASS(BoundedBlockingQueue);
 public:
  explicit BoundedBlockingQueue(size_t max_size): lock_(),
    cond_not_full_(&lock_), cond_not_empty_(&lock_), capacity_(max_size), queue_() {
    }

  ~BoundedBlockingQueue() { }

  // blocking pop
  T Pop() {
    LockGuard<MutexLock> guard(&lock_);
    while (queue_.empty()) {
      cond_not_empty_.Wait();
    }
    assert(!queue_.empty());
    T t = queue_.front();
    queue_.pop_front();
    cond_not_full_.Signal();
    return t;
  }

  // non-blocking pop
  bool TryPop(T& t) {
    LockGuard<MutexLock> guard(&lock_);
    if (!queue_.empty()) {
      t = queue_.front();
      cond_not_full_.Signal();
    }
    return false;
  }

  void Push(const T& t) {
    LockGuard<MutexLock> guard(&lock_);
    while (queue_.size() >= capacity_) {
      cond_not_full_.Wait();
    }
    assert(queue_.size() < capacity_);
    queue_.push_back(t);
    cond_not_empty_.Signal();
  }

  bool TryPush(const T& t) {
    LockGuard<MutexLock> guard(&lock_);
    if (queue_.size() < capacity_) {
      queue_.push_back(t);
      cond_not_empty_.Signal();
      return true;
    }
    return false;
  }

  size_t size() const {
    LockGuard<MutexLock> guard(&lock_);
    return queue_.size();
  }
  bool empty() const {
    LockGuard<MutexLock> guard(&lock_);
    return queue_.empty();
  }
  bool full() const {
    LockGuard<MutexLock> guard(&lock_);
    return queue_.size() == capacity_;
  }
  bool capacity() const {
    LockGuard<MutexLock> guard(&lock_);
    return capacity_;
  }

 private:
  mutable MutexLock lock_;
  ThreadCondition cond_not_full_;
  ThreadCondition cond_not_empty_;
  size_t capacity_;
  std::deque<T> queue_;
};

这里用到了两个条件变量,一个条件变量来判断queue 是否为空,
另一个条件变量来判断 queue 是否为满。利用两个条件变量便可以实现bounded 有边界的条件。

另外一点需要注意私有成员变量 lock_ , 这个变量被声明为mutable.
因为在empty(), full() 等函数中调用,而这些函数声明为const 成员函数。只有把将lock_ 声明为mutable 才能在const 成员函数中改变状态。

有了上面的 BoundedBlockingQueue, 实现一个线程池就比较容易了。
下一篇中来实现一个线程池(threadpool).

网站文章

  • 英飞凌 AURIX TC3xx 烧录程序后没有反应

    英飞凌 AURIX TC3xx 烧录程序后没有反应

    英飞凌 AURIX TC3xx 烧录程序后没有反应,修改芯片UCBs信息中起始地址与代码中的入口地址相对应

    2024-02-01 00:49:55
  • 灰度部署方式

    灰度部署方式

    一蓝绿发布蓝绿发布要求有两套系统,一套提供系统服务,认为是绿色的,另外一套是准备发布的系统,认为是蓝色的。两套系统提供相同的功能,都能提供全量服务。最初只有绿色系统是对外提供服务的,同时准备好具有新特...

    2024-02-01 00:49:50
  • NVIDIA控制面板进行设置时提示“无法应用选定的设置到您的电脑”的解决办法(更新显卡驱动的方法)

    NVIDIA控制面板进行设置时提示“无法应用选定的设置到您的电脑”的解决办法(更新显卡驱动的方法)

    总的来说就是把自己电脑上的显卡驱动进行更新就可以解决这个问题,别的方法不一定能用,另外装载AMD显卡的电脑也是同样的操作,只不过AMD显卡的驱动要去AMD官网进行下载。7.最后找到下载好的NVIDIA...

    2024-02-01 00:49:42
  • 上传文件到阿里oss

    node上传文件到阿里云oss

    2024-02-01 00:49:14
  • MySQL优化

    MySQL优化

    这里特别强调一下分片规则的选择问题,如果某个表的数据有明显的时间特征,比如订单、交易记录等,则他们通常比较合适用时间范围分片,因为具有时效性的数据,我们往往关注其近期的数据,查询条件中往往带有时间字段...

    2024-02-01 00:48:55
  • 继承(Java)

    继承(Java)

    继承定义继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模比如说Person是父类,YellowPerson,WhitePerson,BlackPerson就是子类extends的意思是”扩展...

    2024-02-01 00:48:39
  • DES

    http://www.hankcs.com/security/des-algorithm-illustrated.html

    2024-02-01 00:48:11
  • AsyncLoadScene场景的异步加载---Loading界面

    在游戏开发过程中,常常需要Loading界面。一方面是为了等待后台加载场景;一方面也是为了美观,可以在Loading界面放上游戏里有趣的截图,战斗场面,小提示等。自己最近做的毕业设计中使用了场景的异步加载来使游戏变得更加完整和有趣,这些api用的比较少,所以代码贴上来记录一下。 /* * 所属层级:工具层 * 脚本功能:异步加载场景 * * */ using Uni...

    2024-02-01 00:48:01
  • 江苏大专英语计算机考试,南京农业大学2019年上半年江苏省专科计算机英语统考时间的通知...

    江苏大专英语计算机考试,南京农业大学2019年上半年江苏省专科计算机英语统考时间的通知...

    2019年上半年全省成人高等教育英语、计算机基础课程统考定于6月22日、23日进行。现将有关事宜通知如下:一、考试内容英语课程统考考试大纲不变,与去年考核范围一致。1、计算机基础课程统考中无Micro...

    2024-02-01 00:47:55
  • 数值计算与计算机应用杂志,数值计算与计算机应用杂志

    《数值计算与计算机应用》是由中国科学院数学与系统科学研究院主办的学术性刊物, 季刊,国内外公开发行.《数值计算与计算机应用》主要报道: 应用计算机解决各种科学和工程问题的数学模型、计算方法、软件技术和...

    2024-02-01 00:47:50