开发者社区> 问答> 正文

C++ 线程安全的queue:报错

这个问题在CSDN问过,没有太好答案 。。。。。url:
具体问题可看:
http://bbs.csdn.net/topics/391980811?page=1#post-401328960
因为queue是单线程写入多线程读取的,所以queue需要为线程安全的,下面的设计会出现死锁,应该怎样改造呢? 其中notify 就是pthread里的pthread_cond_signal,wait就是pthread里的pthread_cond_wait

void put(const T& x)

{

ScopeMutexLock lock(m_mutex);

LOG_DEBUG("Queue, put data\n");

m_queue.push_back(x);

LOG_DEBUG("Queue, aftet push_back,size :%ld\n", m_queue.size());

m_notEmpty.notify();

}

T get()

{

ScopeMutexLock lock(m_mutex);

while (m_queue.empty())

{

printf("Queue,in wait\n");

m_notEmpty.wait();

}

LOG_DEBUG("Queue,after wait, will get data\n");

//assert(!m_Queue.empty());

T front(m_queue.front());

m_queue.pop_front();

return front;

}

更多0

展开
收起
kun坤 2020-06-08 19:21:08 819 0
1 条回答
写回答
取消 提交回答
  • 你既然用到了锁,那么你解锁的过程呢?我只看到了加锁啊!目前,看不出来其他的地方还有什么问题######void put(const T& x)

    {

    ScopeMutexLock lock(m_mutex);

    LOG_DEBUG("Queue, put data\n");

    m_queue.push_back(x);

    LOG_DEBUG("Queue, aftet push_back,size :%ld\n", m_queue.size());

    }

    m_notEmpty.notify();

    }

    T get()

    {

    ScopeMutexLock lock(m_mutex);

    while (m_queue.empty())

    {

    printf("Queue,in wait\n");

    m_notEmpty.wait();

    }

    LOG_DEBUG("Queue,after wait, will get data\n");

    //assert(!m_Queue.empty());

    T front(m_queue.front());

    m_queue.pop_front();

    return front;

    }

    notify之前就需要把m_mutex unlock,因为wait函数内部会先unlock再block锁,所以你notify之前不释放锁的话,就会死锁。

    Reference: http://www.cnblogs.com/ngnetboy/p/3521547.html

    ######看不出代码有问题, 把你导致死锁的测试代码贴出来看看。######为什么不在进程里面读队列,之后分配给线程去处理,只要管理好线程的反馈就可以了。######void put(const T& x)

    {

    ScopeMutexLock lock(m_mutex);

    LOG_DEBUG("Queue, put data\n");

    bool need_notify = m_queue.empty();

    m_queue.push_back(x);

    LOG_DEBUG("Queue, aftet push_back,size :%ld\n", m_queue.size());

    if(need_notify){

    m_notEmpty.notify();

    }

    }

    T get()

    {

    ScopeMutexLock lock(m_mutex);

    while(m_queue.empty())

    {

    printf("Queue,in wait\n");

    添加 unlock(m_mutex);

    m_notEmpty.wait();

    重新加锁 lock(m_mutex);

    }

    LOG_DEBUG("Queue,after wait, will get data\n");

    //assert(!m_Queue.empty());

    T front(m_queue.front());

    m_queue.pop_front();

    return front;

    }

    ###### 谢谢各位解答:改为这样已经好,但是如果还用之前的ScopeMutexLock lock(m_mutex) 把notify 放在调用完put的地方调用一遍还是不行
            void put(const T& x)         {                 //printf("queue will lock b put:%p\n",m_mutex.getMutex());                 //ScopeMutexLock lock(m_mutex);                 m_lock->lock();                 printf("Queue, before put data!!!!\n");                 m_queue.push_back(x);                 printf("Queue, aftet put data!!!,size :%ld\n", m_queue.size());                 m_lock->unlock();                 m_notEmpty.notify();         }

            T get()         {                 //printf("queue will lock b get!!!!:%p\n",m_mutex.getMutex());                 //ScopeMutexLock lock(m_mutex);                 m_lock->lock();                 printf("Queue,before get!!!,size:%ld\n",m_queue.size());                 while (m_queue.empty())                 {                         printf("Queue,in wait!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");                         m_notEmpty.wait();                 }                 printf("Queue,after wait!!!!, will get data,queue size:%ld\n",m_queue.size());                 m_lock->unlock();                 //assert(!m_Queue.empty());                 T front(m_queue.front());                 m_queue.pop_front();                 return front;         } ###### 看这个,经典实现
    https://github.com/chenshuo/muduo/blob/master/muduo/base/BlockingQueue.h
    C++ 2011 ######这个不行的,我之前设计的跟他的一样。。。######

    引用来自“hzh62”的评论

    看这个,经典实现 https://github.com/chenshuo/muduo/blob/master/muduo/base/BlockingQueue.h C++ 2011

    这个怎么不行,完全线程安全。。。
    一个锁,两个条件变量的经典实现。
    几行代码,又简单,又清晰。 ######回复 @hzh62 : 看了下资料,你说的在理,虽然问题改好了,但现在认为不是signal的位置导致,准备再跟踪下######回复 @grane : lock 后,unlock 前 发 nodify,这样更安全######看他的put函数,push_back之后 notEmpty_.notify();是在lock之后unlock之前的,这个信号发不出去,必须在unlock之后执行notify,我的测试结果是这样的######要用锁加信号而已。

    2020-06-08 19:21:14
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
使用C++11开发PHP7扩展 立即下载
GPON Class C++ SFP O;T Transce 立即下载
GPON Class C++ SFP OLT Transce 立即下载