参考《深入应用C++11》
SyncQueue.cpp
//同步阻塞队列
#include "SyncQueue.h"
using namespace std;
template<class T>
SyncQueue<T>::SyncQueue(int max_size):max_size(max_size)//这里注意类不能少了类型SyncQueue<T>,因为不同的T是不同的类型
{
}
template<class T>
SyncQueue<T>::~SyncQueue()
{
}
template<class T>
void SyncQueue<T>::put(const T& val)
{
lock_guard<mutex> locker(lock);
while (isFull())
{
cout << "\nQueue is full now, wait a minute!" << endl;
cv_full.wait(lock);
}
q.emplace_back(val);
cv_empty.notify_one();
}
template<class T>
void SyncQueue<T>::take(T& val)
{
lock_guard<mutex> locker(lock);
while (isEmpty())
{
cout << "\nQueue is empty now, wait a minute!" << endl;
cv_empty.wait(lock);
}
val = q.front();
q.pop_front();
cv_full.notify_one();
}
template<class T>
bool SyncQueue<T>::isEmpty()
{
return q.size() == 0;
}
template<class T>
bool SyncQueue<T>::isFull()
{
return q.size() == max_size;
}
template<class T>
int SyncQueue<T>::count()
{
return q.size();
}
SyncQueue.h
#pragma once
#include<mutex>
#include<condition_variable>
#include<list>
#include<iostream>
using namespace std;
template<class T> class SyncQueue
{
public:
SyncQueue(int max_size);
~SyncQueue();
void put(const T& val);
void take(T& val);
bool isEmpty();
bool isFull();
int count();
private:
mutex lock;
condition_variable_any cv_full, cv_empty;
list<T> q;
int size;
int max_size;
};
条件变量的wait方法会释放互斥量,等到notify再重新获取,所以,当队列存满时,put方法会先释放信号量,等take方法被调用后再获取信号量,然后再入队,当队列为空时,take方法会先释放信号量,等put方法被调用后再获取信号量,然后再出队
测试代码:
#include <thread>
#include <iostream>
#include <future>
#include <chrono>
#include <windows.h>
#include <atomic>
#include "SyncQueue.cpp"//注意这里是cpp
using namespace std;
SyncQueue* q = new SyncQueue(3);
atomic<int> task;
void put()
{
int i = 6;
while (i-- > 0)
{
q->put(task++);
cout << "\nput success, size now is " << q->count() << endl;
this_thread::sleep_for(chrono::seconds(1));
}
}
void take()
{
int ret = 0;
while (true)
{
this_thread::sleep_for(chrono::seconds(2));
q->take(ret);
cout << "\ntake success, value is: " << ret << endl;
}
}
int main()
{
task = 0;
thread t1(put);
thread t2(take);
t1.join();
t2.join();
system("pause");
return 0;
}
开启两个线程t1,t2,t1每隔一秒向队列添加一个数,总共添加6个数,t2每隔两秒从队列取一个数
测试结果:
put success, size now is 1
put success, size now is 2
take success, value is: 0
put success, size now is 2
put success, size now is 3
take success, value is: 1
put success, size now is 3
Queue is full now, wait a minute!
take success, value is: 2
put success, size now is 3
take success, value is: 3
take success, value is: 4
take success, value is: 5
Queue is empty now, wait a minute!