多线程设计模式:Guarded Suspensi…

来源:互联网 发布:ubuntu mate 输入法 编辑:程序博客网 时间:2024/05/01 07:59
    GuardedSuspension模式用一句话可以而总结:锁歪等干通。
   解释下,他的基本流程是,锁 —— while循环 —— 若不满足条件等待在条件变量 —— 干活 ——如果有必要调用条件变量的通知。这基本上是条件变量的唯一正确写法。如果你使用条件变量却发现不是走在这条路上,要小心一点。程序员用代码说话,上代码:
   Java版本,实现一个消息队列:
====================================
import java.util.LinkedList;
 
public class RequestQeuee {
    privatefinal LinkedList queue = new LinkedList();
    publicsynchronized Request getRequest() {
        while(queue.size<= 0) {
            try{
                wait();
            }catch(InterruptedException e){
                //忽略
            }
        }
        return(Request)queue.removeFirst();
    }
    publicsynchronized void putRequest(Request request) {
        queue.addLast(request);
        notifyAll();
    }
}
====================================
    C++boost版本,也是实现消息队列,功能比较强,但锁歪等干通的流程一样
====================================
#include<boost/shared_array.hpp>
#include <boost/thread.hpp>
#include <stdexcept>
#include <queue>

class MsgQueue
{
public:

 
  typedef boost::shared_array<char>Msg;

   MsgQueue(std::size_t max_size_)
      : max_size(max_size_)
      , close_flag(false)
   {
      if (max_size < 1)
      {
         throw std::runtime_error("MsgQueue::MsgQueue : max_size< 1");
      }
   }

   ~MsgQueue()
   {
      close();      
   }

   void push(Msg msg)
     
      boost::mutex::scoped_lock lock(mtx);
      while (msgs.size() >= max_size&& !close_flag)
              
         full_cond.wait(lock);
      }
      if (close_flag)
      {
         throw std::runtime_error("MsgQueue::push : msg queue has beenshutdown.");
      }
      msgs.push(msg);
      if(msgs.size() == 1)
      {
         empty_cond.notify_all();   
           
   }
   
   Msg pop()
   {
      boost::mutex::scoped_lock lock(mtx);
      while (msgs.empty() &&!close_flag)
              
         empty_cond.wait(lock);
      }
      if (close_flag)
      {
         throw std::runtime_error("MsgQueue::pop : msg queue has beenshutdown.");
      }
      Msg msg = msgs.front();
      msgs.pop();
      if(msgs.size() == max_size - 1)
      {
         full_cond.notify_all();   
           
      return msg;
   }

   void close()
   {
      close_flag = true;
      {
         boost::mutex::scoped_lock lock(mtx);
         full_cond.notify_all();   
         empty_cond.notify_all();
           
   }  

private:

   boost::mutex mtx;
   boost::condition_variable_any full_cond;
   boost::condition_variable_any empty_cond;
   
   std::queue<Msg>msgs;   
   std::size_t const max_size;
   bool close_flag;
};

  
0 0