Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 线程连接挂起_C++_Multithreading - Fatal编程技术网

C++ 线程连接挂起

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(

线程连接在单个生产者和多个消费者的情况下挂起。 我附上以下代码库:

1) 这是消费者线程

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);