整理自C++并发编程实战
使用std::shared_ptr<>的线程安全队列
/*
* threadsafe_queue_ptr.cpp
*
* Created on: Mar 2, 2018
* Author: clh01s@163.com
* 为了防止在wait_and_pop()中引发异常,
* 所以将shared_ptr<>的初始化移动到push()
* 调用,并且存储shared_ptr<>的实例而不是
* 存储值。将内部的queue复制到shared_ptr<>
* 并不会引发异常。
*/
#include <iostream>
#include <queue>
#include <mutex>
#include <memory>
#include <condition_variable>
using namespace std;
template<typename T>
class threadsafe_queue
{
public:
threadsafe_queue(){}
void wait_and_pop(T& value)
{
//使用了条件变量之后如果队列中没有元素会等待队列push之后再pop,这里需要操作队列所以解锁互斥锁
unique_lock<mutex> lk(_mut);
cout<<"解锁_mut"<<endl;
//调用等待函数时使用lambda判断队列中是否为空
_data_cond.wait(lk,[this]{return !_data_queue.empty();});
value = std::move(*_data_queue.front());
_data_queue.pop();
}
bool try_pop(T& value)
{
//为了防止竞争先加锁队列
lock_guard<mutex> lk(_mut);
cout<<"加锁_mut"<<endl;
//如果
if(_data_queue.empty())
return false;
value = move(*_data_queue.front());
cout<<"pop:"<<value<<endl;
_data_queue.pop();
return true;
}
shared_ptr<T> wait_and_pop()
{
unique_lock<mutex> lk(_mut);
cout<<"等待pop"<<endl;
//在pop之前确认队列中是否有元素,否则不解锁
_data_cond.wait(lk,[this]{return !_data_queue.empty();});
cout<<"开始pop"<<endl;
shared_ptr<T> res = _data_queue.front();
_data_queue.pop();
return res;
}
shared_ptr<T> try_pop()
{
lock_guard<mutex> lk(_mut);
if(_data_queue.empty())
return shared_ptr<T>();
shared_ptr<T> res = _data_queue.front();
_data_queue.pop();
return res;
}
void push(T new_value)
{
shared_ptr<T> data(
make_shared<T>(move(new_value)));
lock_guard<mutex> lk(_mut);
_data_queue.push(data);
//唤醒一个线程供给wait_and_pop使用
_data_cond.notify_one();
}
bool empty() const
{
lock_guard<mutex> lk(_mut);
return _data_queue.empty();
}
private:
//互斥锁变量
mutable mutex _mut;
//使用智能指针保存的队列类型
queue<shared_ptr<T> > _data_queue;
//条件变量
condition_variable _data_cond;
};
int main()
{
threadsafe_queue<int> my_queue;
my_queue.push(1);
my_queue.push(2);
my_queue.push(3);
my_queue.push(4);
my_queue.push(5);
my_queue.push(6);
my_queue.push(7);
int a = 1;
my_queue.try_pop(a);
shared_ptr<int> i = my_queue.try_pop();
cout<<"try_pop pop出的数是:"<<*i<<endl;
i = my_queue.wait_and_pop();
cout<<"wait_and_pop pop出的数是:"<<*i<<endl;
return 0;
}
运行结果:
clh01s@clh01s:~/testcode/并发$ g++ threadsafe_queue_ptr.cpp -pthread -std=c++11
clh01s@clh01s:~/testcode/并发$ ./a.out
加锁_mut
pop:1
try_pop pop出的数是:2
等待pop
开始pop
wait_and_pop pop出的数是:3