C++11中的条件变量提供了用户等待的同步机制,在同步队列的应用中有很大的便利。
简单同步队列代码如下(SimpleSyncQueue.h):
1 #ifndef SIMPLESYNCQUEUE_H 2 #define SIMPLESYNCQUEUE_H 3 4 #include <thread> 5 #include <condition_variable> 6 #include <mutex> 7 #include <list> 8 #include <iostream> 9 10 using namespace std; 11 12 template<typename T> 13 class SimpleSyncQueue 14 { 15 public: 16 SimpleSyncQueue() 17 { 18 19 } 20 21 void Put(const T& x) 22 { 23 //调用Put函数的线程获取互斥量,如果互斥量正在被占用,将等待 24 std::lock_guard<std::mutex> lk(m_mutex); 25 26 //保存数据 27 m_queue.push_back(x); 28 29 //通知等待m_notEmpty的线程 30 m_notEmpty.notify_one(); 31 } 32 33 void Take(T& x) 34 { 35 //调用Take函数的线程获取互斥量,如果互斥量正在被占用,将等待 36 std::unique_lock<std::mutex> locker(m_mutex); 37 38 m_notEmpty.wait(locker,[this] { 39 40 if(m_queue.empty()) 41 { 42 cout<<"现在队列为空,请稍等"<<endl; 43 } 44 45 return !m_queue.empty(); 46 }); 47 48 x = m_queue.front(); 49 m_queue.pop_front(); 50 } 51 52 bool Empty() 53 { 54 std::lock_guard<std::mutex> lk(m_mutex); 55 56 return m_queue.empty(); 57 } 58 59 size_t Size() 60 { 61 std::lock_guard<std::mutex> lk(m_mutex); 62 63 return m_queue.size(); 64 } 65 66 private: 67 std::list<T> m_queue; /* 用于等待的同步变量 */ 68 std::mutex m_mutex; /* 用于多线程同步的互斥量 */ 69 std::condition_variable m_notEmpty; /* 用于等待的同步变量 */ 70 }; 71 72 73 74 #endif // SIMPLESYNCQUEUE_H
测试代码如下:
1 #include <QCoreApplication> 2 3 #include "simplesyncqueue.h" 4 5 SimpleSyncQueue<int> testQueue; 6 bool threadrun = true; 7 8 void consumerthread() 9 { 10 int get; 11 12 while(threadrun) 13 { 14 testQueue.Take(get); 15 16 cout<<"consumer thread get: "<<get<<endl; 17 } 18 19 cout<<"consumerthread exit"<<endl; 20 } 21 22 void producerthread() 23 { 24 char in = 0; 25 26 while(threadrun) 27 { 28 cin>>in; 29 30 cout<<"user input: "<<in<<endl; 31 32 switch(in) 33 { 34 case 'p': testQueue.Put((int)100); break; 35 case 'q': threadrun = false; break; 36 default: break; 37 } 38 } 39 40 cout<<"producerthread exit"<<endl; 41 } 42 43 int main(int argc, char *argv[]) 44 { 45 QCoreApplication a(argc, argv); 46 47 std::thread t1(consumerthread); 48 49 std::thread t2(producerthread); 50 t1.detach(); 51 52 t2.join(); 53 54 cout<<"program exit"<<endl; 55 56 return a.exec(); 57 }
测试结果如下:
看看condition_variable类中的wait函数定义,参见http://en.cppreference.com/w/cpp/thread/condition_variable/wait
关于这个函数,其实疑惑的是pred ()函数会被执行多少遍的问题。cppreference里的详解里给了一个 Equivalent to:
while (!pred()) {
wait(lock);
}
从Equivalent To可以看到pred开始被执行一次。