等待分离的线程在C++中完成

Tim*_*Tim 8 c++ multithreading corba pthreads

我怎么能等待分离的线程在C++中完成?

我不关心退出状态,我只是想知道线程是否已经完成.

我正在尝试围绕异步的第三方工具提供同步包装器.问题是涉及回调的奇怪的竞争状态崩溃.进展如下:

  1. 我打电话给第三方,并注册一个回调
  2. 当第三方完成时,它通知我使用回调 - 在一个分离的线程中,我没有真正的控制权.
  3. 我希望(1)中的线程等到(2)被调用.

我想在一个提供阻塞调用的机制中包装它.到目前为止,我有:

class Wait {
  public:
  void callback() {
    pthread_mutex_lock(&m_mutex);
    m_done = true;
    pthread_cond_broadcast(&m_cond);
    pthread_mutex_unlock(&m_mutex);
  }

  void wait() {
    pthread_mutex_lock(&m_mutex);
    while (!m_done) {
      pthread_cond_wait(&m_cond, &m_mutex);
    }
    pthread_mutex_unlock(&m_mutex);
  }

  private:
  pthread_mutex_t m_mutex;
  pthread_cond_t  m_cond;
  bool            m_done;
};

// elsewhere...
Wait waiter;
thirdparty_utility(&waiter);
waiter.wait();
Run Code Online (Sandbox Code Playgroud)

据我所知,这应该有效,而且通常会有效,但有时它会崩溃.至于我可以从corefile中确定,我对这个问题的猜测是这样的:

  1. 当回调广播m_done的结束时,等待线程唤醒
  2. 等待线程现在在这里完成,Wait被破坏.Wait的所有成员都被销毁,包括互斥锁和cond.
  3. 回调线程尝试从广播点继续,但现在使用已释放的内存,这会导致内存损坏.
  4. 当回调线程试图返回时(高于我糟糕的回调方法的级别),程序崩溃(通常使用SIGSEGV,但我已经看过几次SIGILL).

我尝试了很多不同的机制来尝试解决这个问题,但没有一个能解决问题.我仍然偶尔看到崩溃.

编辑:更多细节:

这是大规模多线程应用程序的一部分,因此创建静态等待是不切实际的.

我运行了一个测试,在堆上创建Wait,并故意泄漏内存(即Wait对象永远不会被释放),这导致没有崩溃.所以我确定这是等待太快解除分配的问题.

我也尝试过sleep(5)在解锁后进行测试wait,并且也没有发生崩溃.我讨厌依靠这样的kludge.

编辑:ThirdParty详细信息:

我一开始并不认为这是相关的,但我想的越多,我认为这就是真正的问题:

我提到的第三方的东西,以及为什么我无法控制线程:这是使用CORBA.

因此,CORBA可能会比我预期的更长时间地保持对对象的引用.

Ada*_*ode 3

是的,我相信您所描述的情况正在发生(解除分配时的竞争条件)。解决此问题的一种快速方法是创建一个不会被销毁的 Wait 静态实例。只要您不需要同时有超过一名服务员,这种方法就可以发挥作用。

您还将永久使用该内存,它不会释放。但看起来这并不算太糟糕。

主要问题是很难协调线程之间的线程通信构造的生命周期:当可以安全销毁时,您总是需要至少一个剩余的通信构造来进行通信(至少在没有垃圾收集的语言中,如 C++)。

编辑:有关使用全局互斥体重新计数的一些想法,请参阅评论。