C/C++ 线程安全队列

一、简介

线程安全是一个比较严肃的问题,如果处理不好,可能导致数据被破坏,程序崩溃等问题,如何来处理多线程的并发问题?在windows平台有相应的api给你用于控制并发,如互斥锁,信号量,事件,临界区等,定要熟练掌握,当然现在STL库已强大到兼容不同的硬件系统了,当然对于winApi同步可以看这里:
互斥锁,信号量,事件,临界区详情

二、分析安全原理

基于conditon_variable类实现线程安全,先来看看它有什么API使

wait阻塞自己,等待唤醒

wait_for阻塞自己,等待唤醒,最多等待一段时间

wait_until阻塞自己,等待唤醒,最多等待到某个时间点

notify_one 唤醒一个等待在这个条件变量上的线程

notify_all 唤醒所有等待在这个条件变量上的线程

这个有点类似的于event,想让某处导通就直接setEvent,
某博主的关于condition_variable比较详细的讲解:点此

三、上队列代码

template<typename T> class ThreadSafe_Queue
{
private:
    mutable mutex m_mut;
    queue<T> m_queue;
    condition_variable m_data_cond;
public:
    ThreadSafe_Queue() {}
    ThreadSafe_Queue(const ThreadSafe_Queue&) = delete;
    void push(T data)
    {
        lock_guard<mutex> lg(m_mut);
        m_queue.push(data);
        m_data_cond.notify_one();
    }
    void WaitPop(T&t)
    {
        unique_lock<mutex> ul(m_mut);
        m_data_cond.wait(ul, [this] {return !m_queue.empty(); });
        t = m_queue.front();
        m_queue.pop();
    }
    shared_ptr<T> WaitPop()
    {
        unique_lock<mutex> ul(m_mut);
        m_data_cond.wait(ul, [this] {return !m_queue.empty(); });

        shared_ptr<T> res(make_shared<T>(m_queue.front()));
        m_queue.pop();
        return res;
    }
    bool TryPop(T &t)
    {
        lock_guard<mutex> lg(m_mut);
        if (m_queue.empty())
            return false;

        t = m_queue.front();
        m_queue.pop();
        return true;
    }

    shared_ptr<T> TryPop()
    {
        lock_guard<mutex> lg(m_mut);
        if (m_queue.empty())
            return shared_ptr<T>();
        shared_ptr<T> res(make_shared<T>(m_queue.front()));
        m_queue.pop();
        return res;
    }

    bool IsEmpty()
    {
        lock_guard<mutex> lg(m_mut);
        return m_queue.empty();
    }

};

四、一个小例子

开了两个线程,用于测试线程队列是否安全,thread_Fuc2用于插入数据,thread_Fuc用于出队操作,经过测试,达到了安全。

ThreadSafe_Queue<int> g_queue;
int g_index = 10;

void thread_Fuc()
{
    cout << "thread_fuc1 start\n";
    while (true)
    {
        int value=0;
        g_queue.WaitPop(value);
        printf("wait_and_pop done! value=%d  thread id:%d\n",value,GetCurrentThreadId());
    }
}

void thread_Fuc2()
{
    cout << "thread_fuc2 start\n";
    while (true)
    {
        Sleep(1000);
        g_index++;
        g_queue.push(g_index);
    }
}

int main()
{
    thread thd(thread_Fuc);
    thd.detach();

    thread thd2(thread_Fuc2);
    thd2.detach();

    int a;
    while (cin >> a){;}
    return 0;
}

测试图:
这里写图片描述


更多文章:http://blog.csdn.net/what951006?viewmode=list
powered by:小乌龟在大乌龟背上~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值