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

来源:互联网 发布:如何优化前端页面 编辑:程序博客网 时间:2024/06/13 18:14

线程安全队列

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

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

  1. thread 线程库
  2. 同步和互斥有关量mutexcondition_variable
  3. 简单的资源管理类:lock_guard,unique_lock,shared_ptr.
  4. 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;}

测试结果如下:

simple test:

0 0
原创粉丝点击