shared_ptr 与 QThreadPool

Posted

技术标签:

【中文标题】shared_ptr 与 QThreadPool【英文标题】:shared_ptr with QThreadPool 【发布时间】:2014-03-31 04:49:22 【问题描述】:

我目前正在将共享指针与 QThreadPool 一起用于多线程应用程序。但是,当线程完成计算时,我遇到了崩溃。

假设 A 类继承自 QRunnable,当将共享指针作为参数传入时,它会更新其类变量。代码如下:

for(int i=0;i<1000;i++)

    boost::shared_ptr<VariableType> variable = boost::make_shared<VariableType>();
    variable->Update_One_InternalVariable(1); // just updating a class variable inside VariableType

    Class* A = new Class(variable);
    A->setAutoDelete(true);

    QThreadPool::globalInstance()->start(A);

    m_thread_count++;

    if(m_thread_count >0 && m_thread_count %4== 0)
    
        QThreadPool::globalInstance()->waitForDone(); // crashes after all threads finished here
    

QThreadPool::globalInstance()->waitForDone();

在 4 个线程执行并结束后不久发生崩溃。我假设当 QThreadPool 尝试删除这些线程时会发生崩溃?有人可以指出我在多线程环境中使用共享指针是否做错了什么?

【问题讨论】:

没有足够的信息来知道你做错了什么。其次,无论如何,您都不应该使用该全局 m_thread_count 来计算线程 - QThreadPool 会为您处理这个问题。最后,如果您想知道 shared_ptr 是否会导致问题,只需传入普通指针并查看它是否崩溃(对于您的示例,无论如何使用 unique_ptr 可能会更好).. 祝你好运。 为什么要调用 waitForDone 所有四个迭代?它阻塞并销毁线程。线程重用是使用线程池的要点。只需将它们全部传递给 start(),线程池会将可运行对象排入队列。 去掉QThreadPool::globalInstance()->waitForDone();在循环中,它甚至更早崩溃。不过,在这种情况下,我有时设法绕过了许多交互。它不是调用 waitForDone 所有四个交互。它正在阻止排队等候的太多事情。许多人建议不要使用它,但它似乎为我解决了一些问题。这就是为什么我怀疑问题出在我的 A 类中。shared_ptr 线程是否安全? 【参考方案1】:

shared_ptr 不是线程安全的,因为不允许从多个线程访问 同一个实例。但是,使用两个指向同一个对象的shared_ptr 的不同实例是线程安全的,只要该对象本身是线程安全的。另见the documentation

因此,如果您将 shared_ptr 作为引用存储在 Class 中,则可能会崩溃。改为复制shared_ptr

【讨论】:

事实上,这也适用于 Qt 中的所有隐式共享类:所有模板化容器、QStringQImage

以上是关于shared_ptr 与 QThreadPool的主要内容,如果未能解决你的问题,请参考以下文章

动态内存与智能指针

[C++11]shared_ptr共享智能指针的初始化与使用

智能指针std::shared_ptr总结与使用

std::shared_ptr 在不同计算机上与 MSVC 崩溃?

c_cpp shared_ptr用法与地图中的引用计数

智能指针循环引用--转