【问题标题】:How to safely delete a thread pointer in a destructor?如何安全地删除析构函数中的线程指针?
【发布时间】:2014-12-07 18:31:40
【问题描述】:

比如说,我有一个 C++ 类,其中包含一个线程指针作为成员变量。线程一直运行直到程序退出。 如果我删除析构函数中的指针,那一刻似乎线程还没有完成?管理这个或任何技巧的最佳做法是什么?

示例代码:

class Car {
public:
    Car();
    ~Car();
private:
    boost::thread *m_runningThreadPtr;
};


Car::Car() {
    m_runningThreadPtr = new boost::thread();
}

Car::~Car() {
    delete m_runningThreadPtr;    // The thread should be still running now. 
                                  // Problematic if it was deleted here?
}

【问题讨论】:

标签: c++ multithreading


【解决方案1】:

默认情况下,如果线程仍在运行,析构函数将调用terminate() 来杀死线程,这是否安全取决于线程当时正在做什么。如果你想等待线程完成,你可以在删除它之前调用join(),并使用某种同步系统(甚至只是一个全局标志)来告诉线程退出。

【讨论】:

  • 请注意这是boost::thread,而不是std::thread。它将调用detach,而不是terminate。就目前而言,删除线程对象是“无害的”(尽管仍然不可取),因为分离的线程不会被杀死。
【解决方案2】:

这取决于您要寻找什么样的行为。

如果你想删除对象,让它停止它拥有的线程,然后删除它的线程对象,那么你应该有一个停止标志,你的线程会不时检查它。在析构函数中,您将设置停止标志,然后在您的线程上调用join()。一旦它返回,你就可以安全地删除指针了。

另一方面,如果你想删除对象并让线程自行运行直到它完成,那么你需要一个更聪明的机制,比如在你的线程函数结束时,发布到主线程您的应用程序的回调,在您的线程上调用join(),然后deletes 它。为此,当然,你需要在你的线程函数中有一个指向你的线程对象的指针。

编辑 对于boost::thread,它只是在其析构函数中分离,因此对于第二个选项,您可以在完成后安全地删除它。 然而,重要的是要注意,这不适用于std::thread 的析构函数,在这种情况下它将终止您的程序。但是你也可以手动调用detach(),然后再调用delete。所以你真的必须看看你正在使用的 API。

【讨论】:

    【解决方案3】:

    不要删除它。完成后让线程自行删除。

    【讨论】:

    • 这可能很危险,具体取决于 API。例如。线程对象的析构函数可能会在其自身上调用join(),从而有效地导致死锁。
    【解决方案4】:

    当没有更多代码可以运行时,您的程序就完成了。你的线程还在运行代码吗?那你为什么认为你的程序已经完成了?

    因此,假设您的线程实际上已经完成是合理的。这意味着你可以在线程上调用.join(),之后调用delete就可以了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-30
      • 1970-01-01
      • 1970-01-01
      • 2013-10-01
      • 2021-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多