C++ 线程连接挂起
线程连接在单个生产者和多个消费者的情况下挂起。 我附上以下代码库: 1) 这是消费者线程C++ 线程连接挂起,c++,multithreading,C++,Multithreading,线程连接在单个生产者和多个消费者的情况下挂起。 我附上以下代码库: 1) 这是消费者线程 class ConsumerThread- { wqueue<WorkItem*>& m_queue; - public: ConsumerThread(wqueue<WorkItem*>& queue) : m_queue(queue) {} std::thread start() { return std::thread(
class ConsumerThread-
{
wqueue<WorkItem*>& m_queue;
-
public:
ConsumerThread(wqueue<WorkItem*>& queue) : m_queue(queue) {}
std::thread start() {
return std::thread( [=] {runThr();} );
}
-
void runThr() {
// Remove 1 item at a time and process it. Blocks if no items are-
// available to process.
for (int i = 0;; i++) {
printf("thread %lu, loop %d - waiting for item...\n",-
std::this_thread::get_id(), i);
WorkItem* item = (WorkItem*)m_queue.remove();
printf("thread %lu, loop %d - got one item\n",-
std::this_thread::get_id(), i);
printf("thread %lu, loop %d - item: message - %s, number - %d\n",-
std::this_thread::get_id(), i, item->getMessage(),-
item->getNumber());
delete item;
}
}
};
3) 。此类具有生产者推送和使用者使用工作项的队列
template <typename T> class wqueue
{
std::list<T> m_queue;
std::mutex m_mutex;
std::condition_variable m_condv;-
public:
wqueue() {}
~wqueue() {}
void add(T item) {
m_mutex.lock();
m_queue.push_back(item);
m_condv.notify_one();
m_mutex.unlock();
}
T remove() {
std::unique_lock<std::mutex> lk(m_mutex);
while(m_queue.size() == 0)
m_condv.wait(lk);
T item = m_queue.front();
m_queue.pop_front();
return item;
}
int size() {
m_mutex.lock();
int size = m_queue.size();
m_mutex.unlock();
return size;
}
};
模板类wqueue
{
std::列表m_队列;
std::mutex m_mutex;
std::条件变量m_condv-
公众:
wqueue(){}
~wqueue(){}
无效添加(T项){
m_mutex.lock();
m_队列。推回(项目);
有条件通知某人;
m_mutex.unlock();
}
T删除(){
std::唯一锁lk(m_互斥);
while(m_queue.size()==0)
m_condv.wait(lk);
T item=m_queue.front();
m_queue.pop_front();
退货项目;
}
int size(){
m_mutex.lock();
int size=m_queue.size();
m_mutex.unlock();
返回大小;
}
};
4) 这是包含主函数的类
int main(int argc, char* argv[])
{
// Process command line arguments
if ( argc != 2 ) {
printf("usage: %s <iterations>\n", argv[0]);
exit(-1);
}
int iterations = atoi(argv[1]);
// Create the queue and consumer (worker) threads
wqueue<WorkItem*> queue;
ConsumerThread* thread1 = new ConsumerThread(queue);
ConsumerThread* thread2 = new ConsumerThread(queue);
std::thread t1 = thread1->start();
std::thread t2 = thread2->start();
t1.join();
t2.join();
// Add items to the queue
WorkItem* item;
for (int i = 0; i < iterations; i++) {
item = new WorkItem("abc", 123);
queue.add(item);
item = new WorkItem("def", 456);
queue.add(item);
item = new WorkItem("ghi", 789);
queue.add(item);
}
intmain(intargc,char*argv[])
{
//处理命令行参数
如果(argc!=2){
printf(“用法:%s\n”,argv[0]);
出口(-1);
}
int迭代次数=atoi(argv[1]);
//创建队列和使用者(工作者)线程
排队;
ConsumerThread*thread1=新的ConsumerThread(队列);
ConsumerThread*thread2=新的ConsumerThread(队列);
std::thread t1=thread1->start();
std::thread t2=thread2->start();
t1.join();
t2.连接();
//将项目添加到队列中
工作项目*项目;
对于(int i=0;i
第4节中提到的t1.join()和t2.join()挂起。您的使用者线程没有终止条件,因此它将永远运行:
for (int i = 0;; i++) // never ends
加入一个线程并不会神奇地使它脱离循环,你需要设置一个结束标志或其他东西
另外,当wqueue
为空时,所有试图remove()
元素的线程都将阻塞:
while(m_queue.size() == 0)
m_condv.wait(lk);
在将任何内容放入线程之前,请尝试
join()
线程。这种行为没有问题,对线程对象调用join()
只需等待线程完成后再继续。问题在于线程没有终止,这是一个完全不同的问题
特别是在生产者-消费者设置中,两个对等方通常都坐着等待工作。除非你明确告诉他们不要再等待工作,否则他们将永远坐在那里!如果你依次等待他们完成,你也将永远等待,这是你的问题。你需要向他们发出停止循环的信号,此外,你可能没有o中断他们等待工作。
join()
(等待线程结束的执行),然后将项目添加到队列中?这看起来很奇怪。当执行t1.join()
和t2.join()
时,队列中没有项目,因此线程将挂起在WorkItem*(WorkItem*)m_队列中。remove()
程序实际上挂起在join()上,而不是remove()。以下是回溯信息。#0 0x0000003c0200822d在pthread_join()中来自/lib64/libpthread.so.0#1 0x00007FF7D9F09A在uu gthread_ujoin中(此=0x7fffffffe240)在/opt/tools/compile/gcc-4.5.3/x86#u 64-unknown-linux-gnu++-v3/include/x86#u 64-unknown-linux-gnu/bits/gthr default.h:658#2 std::thread::join(this=0x7fffffffe240)at../../.././libstdc++-v3/src/thread.cc:61#3 0x0000000000414cc在main()真的吗?你是否在runThr()中打印了什么来检查它
?线程139685266667264,循环0-等待项目…线程139685256177408,循环0-等待项目…下面是print in runThr()语句。我为(int I=0;I<1000;I++)制作了它。它仍然不工作。我在生产者代码之后调用了下面的代码,它工作了。感谢您的回复。WorkItem*item;for(inti=0;i while(m_queue.size() == 0)
m_condv.wait(lk);