C++并发实战11:线程安全的queue

2014-11-24 03:25:52 · 作者: · 浏览: 1

1 首先看下STL中的queue的接口:

template 
  
    >
class queue {
  public:
    explicit queue(const Container&);
    explicit queue(Container&& = Container());
    template 
   
     explicit queue(const Alloc&); template 
    
      queue(const Container&, const Alloc&); template 
     
       queue(Container&&, const Alloc&); template 
      
        queue(queue&&, const Alloc&); void swap(queue& q); bool empty() const; size_type size() const; T& front(); const T& front() const; T& back(); const T& back() const; void push(const T& x); void push(T&& x); void pop(); template 
       
         void emplace(Args&&... args); };
       
      
     
    
   
  

STL中的queue是非线程安全的,一个组合操作:front(); pop()先读取队首元素然后删除队首元素,若是有多个线程执行这个组合操作的话,可能会发生执行序列交替执行,导致一些意想不到的行为。因此需要重新设计线程安全的queue的接口。

2 简化的线程安全的queue接口

#include 
  
    
template
   
     class threadsafe_queue { public: threadsafe_queue(); threadsafe_queue(const threadsafe_queue&); threadsafe_queue& operator=(const threadsafe_queue&) = delete;//禁止赋值操作是为了简化 void push(T new_value); bool try_pop(T& value);//尝试删除队首元素,若删除成功则通过value返回队首元素,并返回true;若队为空,则返回false std::shared_ptr
    
      try_pop();//若队非空shared_ptr返回并删除的队首元素;若队空,则返回的shared_ptr为NULL void wait_and_pop(T& value);//若队非空,通过value返回队首元素并删除,函数返回true;若队为空,则通过condition_variable等待有元素入队后再获取闭并删除队首元素 std::shared_ptr
     
       wait_and_pop();//和前面一样,只不过通过shared_ptr返回队首元素 bool empty() const; };
     
    
   
  


3 实现threadsafe_queue

#include 
  
   
#include 
   
     #include 
    
      #include 
     
       template
      
        class threadsafe_queue { private: mutable std::mutex mut; std::queue
       
         data_queue; std::condition_variable data_cond; public: threadsafe_queue(){} threadsafe_queue(threadsafe_queue const& other) { std::lock_guard
        
          lk(other.mut); data_queue=other.data_queue; } void push(T new_value)//入队操作 { std::lock_guard
         
           lk(mut); data_queue.push(new_value); data_cond.notify_one(); } void wait_and_pop(T& value)//直到有元素可以删除为止 { std::unique_lock
          
            lk(mut); data_cond.wait(lk,[this]{return !data_queue.empty();}); value=data_queue.front(); data_queue.pop(); } std::shared_ptr
           
             wait_and_pop() { std::unique_lock
            
              lk(mut); data_cond.wait(lk,[this]{return !data_queue.empty();}); std::shared_ptr
             
               res(std::make_shared
              
               (data_queue.front())); data_queue.pop(); return res; } bool try_pop(T& value)//不管有没有队首元素直接返回 { std::lock_guard
               
                 lk(mut); if(data_queue.empty()) return false; value=data_queue.front(); data_queue.pop(); return true; } std::shared_ptr
                
                  try_pop() { std::lock_guard
                 
                   lk(mut); if(data_queue.empty()) return std::shared_ptr
                  
                   (); std::shared_ptr
                   
                     res(std::make_shared
                    
                     (data_queue.front())); data_queue.pop(); return res; } bool empty() const { std::lock_guard
                     
                       lk(mut); return data_queue.empty(); } };