namespacemulti_thread{template<typenameTask>classthread_safe_queue{public:thread_safe_queue():done_(false){}voidpush(constTask&t){std::lock_guard<std::mutex>lock(mtx_);queue_.push(t);ready_.notify_one();}voidwait_and_pop(Task&t){std::unique_lock<std::mutex>lock(mtx_);if(queue_.empty()&&!done_)ready_.wait(lock);if(done_)return; t =queue_.front();queue_.pop();}boolempty()const{std::lock_guard<std::mutex>lock(mtx_);returnqueue_.empty();}voidclear(){std::lock_guard<std::mutex>lock(mtx_);for(int i =0; i <queue_.size();++i)queue_.pop();}voiddone(){ done_ =true;ready_.notify_all();}private:std::queue<Task> queue_;mutablestd::mutex mtx_;std::condition_variable ready_;std::atomic_bool done_;};}
这里我们采用了std::mutex作为我们的互斥量,每次访问队列中的内容时,都用std::lock_guard或者std::unique_lock加锁,保证在同一时段只有一个线程可以读写队列。std::lock_guard是一个方便的RAII的体现,他会在析构时自动调用unlock(),std::unique_lock与之的区别就是,你可以显式调用unlock()函数完成解锁,它更加的灵活,当然你可以用{}和std::lock_guard完成相同的工作。我们将std::mutex_设计成mutable,是因为我们需要在const member functionempty()中使用它。