muduo-base源码分析(三)—— 有界队列和无界队列

队列是在网络编程中是一个很重要的模块,很多地方都会使用到队列【例如线程池】;多个线程都可以对队列进行操作,从而带来同步问题,而解决队列同步的一个主要方式就是 生产者消费者模式

生产者消费者模式

处理生产者消费问题可以用 mutex + sem 或者 mutex + conditionmuduo 库中使用的是 mutex + condition,所以我就使用一个简单的模型来讲解这个问题

//没有上界的生产者消费者
queue<int> q;		//队列,FIFO
mutex_t mutex;		
condition_t cond;

//消费者
void consumer() {
	mutex.lock();
	while(!q.empty()) {
		//等待队列中有元素
		cond.wait();
	}
	int tmp = q.front();
	q.pop();
	cout << tmp << endl;
	mutex.unlock();
}

//生产者
void productor(int num) {
	mutex.lock();
	q.push(num);
	//唤醒等待的线程
	cond.signal();
	//cond.boardcast
	mutex.unlock();
}

-----------------------------------------------------------------
//有上界的生产者消费者模型
queue<int> q;		//队列,FIFO
mutex_t mutex;		
condition_t empty_cond;
condition_t full_cond;
int maxSize = 100;

//消费者
void consumer() {
	mutex.lock();
	while(q.empty()) {
		//等待队列中有元素
		empty_cond.wait();
	}
	int tmp = q.front();
	q.pop();
	cout << tmp << endl;
	//由于取出一个元素了,此时队列不可能满了,唤醒等待不满的线程
	full_cond.signal();
	//full_cond.boardcast();
	mutex.unlock();
}

//生产者
void productor(int num) {
	mutex.lock();
	while(q.size() == maxSize) {
		full_cond.wait();
	}
	q.push(num);
	//唤醒等待的线程
	cond.signal();
	//cond.boardcast
	mutex.unlock();
}
  • 网上有对生产者消费者模式的讲解,我这里只是简单的提一下,感兴趣可以自己去看看;
  • 如果你对这个有了解的话,这个队列是很容易理解和实现的;这里是通过加锁的方式实现的,网上也有通过使用原子操作实现的队列,这个效率很更高,可以去了解一下;
  • 有界和无界的区别就是多了一个条件变量,多了一个等待条件和唤醒;

BlockingQueue 的具体代码

template<typename T>
class BlockingQueue : noncopyable
{
 public:
  using queue_type = std::deque<T>;

  BlockingQueue()
    : mutex_(),
      notEmpty_(mutex_),
      queue_()
  {
  }

  //生产者
  void put(const T& x)
  {
    //加锁
    MutexLockGuard lock(mutex_);
    queue_.push_back(x);
    notEmpty_.notify(); 
    //函数执行完后自动解锁
  }

  //使用右值方式的生产者
  void put(T&& x)
  {
    MutexLockGuard lock(mutex_);
    queue_.push_back(std::move(x));
    notEmpty_.notify();
  }

  //消费者
  T take()
  {
    //加锁
    MutexLockGuard lock(mutex_);
    while (queue_.empty())
    {
      notEmpty_.wait();
    }
    assert(!queue_.empty());
    T front(std::move(queue_.front()));
    queue_.pop_front();
    return front;
    //结束后自动解锁
  }

  //返回队列长度
  size_t size() const
  {
    MutexLockGuard lock(mutex_);
    return queue_.size();
  }

 private:
  mutable MutexLock mutex_;   						//一个互斥量
  Condition         notEmpty_ GUARDED_BY(mutex_);   //一个条件变量
  queue_type        queue_ GUARDED_BY(mutex_);      //模板队列,使用的是 STL 中的 deque
};  // __attribute__ ((aligned (64)));

注意:上面的锁都是封装过的,详细可以去看 mutex.hcondition.h,不是很难;

BoundedBlockingQueue 的具体实现

template<typename T>
class BoundedBlockingQueue : noncopyable
{
 public:
  explicit BoundedBlockingQueue(int maxSize)
    : mutex_(),
      notEmpty_(mutex_),
      notFull_(mutex_),
      queue_(maxSize)
  {
  }


  //生产者
  void put(const T& x)
  {
    MutexLockGuard lock(mutex_);
    while (queue_.full())
    {
      notFull_.wait();
    }
    //wait 最后会加锁
    assert(!queue_.full());
    queue_.push_back(x);
    notEmpty_.notify();
    //函数结束时会自动释放锁
  }

  void put(T&& x)
  {
    MutexLockGuard lock(mutex_);
    while (queue_.full())
    {
      notFull_.wait();
    }
    assert(!queue_.full());
    queue_.push_back(std::move(x));
    notEmpty_.notify();
  }

  //消费者
  T take()
  {
    MutexLockGuard lock(mutex_);
    while (queue_.empty())
    {
      notEmpty_.wait();
    }
    assert(!queue_.empty());
    T front(std::move(queue_.front()));
    queue_.pop_front();
    notFull_.notify();
    return front;
  }

  bool empty() const
  {
    MutexLockGuard lock(mutex_);
    return queue_.empty();
  }

  bool full() const
  {
    MutexLockGuard lock(mutex_);
    return queue_.full();
  }

  //容器使用个数
  size_t size() const
  {
    MutexLockGuard lock(mutex_);
    return queue_.size();
  }

  //容器的总容量
  size_t capacity() const
  {
    MutexLockGuard lock(mutex_);
    return queue_.capacity();
  }

 private:
  mutable MutexLock          mutex_;
  Condition                  notEmpty_ GUARDED_BY(mutex_);  //判断是不是满了
  Condition                  notFull_ GUARDED_BY(mutex_);   //判断是不是空
  boost::circular_buffer<T>  queue_ GUARDED_BY(mutex_);     //环形缓冲区
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值