您的位置:首页 > 编程语言 > C语言/C++

c++11多线程编程---线程安全队列

2016-11-04 00:01 295 查看

线程安全队列

c11正式引入了自己的线程类,让c++的多线程编程变的更加优雅。由于不同的编译器对新特性的支持有所差异,这里的代码都是在gcc 4.8版本下编译运行。

涉及到的C++11的知识如下:

thread 线程库

同步和互斥有关量mutexcondition_variable

简单的资源管理类:lock_guard,unique_lock,shared_ptr.

lambda表达式

底层容器为queue,这里将取元素front() 和弹出pop()操作合并为一个接口,为了防止以下事件:在取元素和弹出元素之间这段时间又有其他线程进行front()或者pop(),出现 错误。

#include <iostream>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <memory>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
using namespace std;

template<typename T>
class safe_queue
{
public:
mutex m_mut;
condition_variable m_cond;
queue<T> m_queue;
public:
safe_queue(){}
safe_queue(const safe_queue& rhs)
{
lock_guard<mutex> lk(rhs.m_mut);
m_queue = rhs;
}
void push(T data)
{
lock_guard<mutex> lk(m_mut);  // 使用效率高的lock_guard
m_queue.push(move(data));  // 移动构造函数,防止对象不能拷贝
m_cond.notify_one(); // 通知唤醒阻塞的一个线程
}
void wait_and_pop(T &res)  // 直到队列不为空
{
unique_lock<mutex> lk(m_mut);
m_cond.wait(lk,[this]{return !m_queue.empty();});
res = move(m_queue.front());
m_queue.pop();
}

bool try_pop(T &res)  //立即返回
{
lock_guard<mutex> lk(m_mut);
if(m_queue.empty())
return false;
res = move(m_queue.front());
return true;
}
/*
下面这种是由返回值返回元素。
*/
shared_ptr<T> wait_and_pop()
{
unique_lock<mutex> lk(m_mut);
m_cond.wait(lk,[this]{return !m_queue.empty();});
shared_ptr<T> res(make_shared<T>(move(m_queue.front())));
m_queue.pop();
return res;
}

shared_ptr<T> try_pop()
{
lock_guard<mutex> lk(m_mut);
if(m_queue.empty())
return NULL;
shared_ptr<T> res(make_shared<T>(move(m_queue.front())));
m_queue.pop();
return res;
}
};


测试:

void func(safe_queue<string> &que)
{
while(1)  // 不断的处理数据
{
string a;
que.wait_and_pop(a);  // 没有元素则阻塞
cout<<"thread_id :"<<this_thread::get_id();
cout<<"  input is: "<<a<<endl;
}
}
int main()
{
safe_queue<string> que;
vector<thread> threads;
for(int i = 0;i<5;++i)  // 这里创建5个测试线程
{
threads.push_back(thread(func,ref(que)));
}
string a;
while(cin>>a)  // 数据准备线程,在不断的获取数据。
{
que.push(a);
}
for_each(threads.begin(),threads.end(),mem_fn(&thread::join));  //调用所有线程的join函数,等待任务完成
return 0;
}


测试结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息