这个问题在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
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
你既然用到了锁,那么你解锁的过程呢?我只看到了加锁啊!目前,看不出来其他的地方还有什么问题######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 : 看了下资料,你说的在理,虽然问题改好了,但现在认为不是signal的位置导致,准备再跟踪下######回复 @grane : lock 后,unlock 前 发 nodify,这样更安全######看他的put函数,push_back之后 notEmpty_.notify();是在lock之后unlock之前的,这个信号发不出去,必须在unlock之后执行notify,我的测试结果是这样的######要用锁加信号而已。