多线程环境中的析构函数?

时间:2016-10-07 20:12:33

标签: c++ multithreading

我想知道在这样一个班级会发生什么:

class MyClass
{
private:
    std::vector<int> iVector;
    void Worker()
    {
        //Lots of stuff done with iVector
        //adding, removing elements, etc.
    }
}

假设我创建了一个使用iVector并修改它的线程(由其中一个类成员函数调用)。除了这个worker之外,该类的其他成员函数都没有读取或修改这个std :: vector。

一切似乎都很好,因为工作线程是唯一使用iVector的人。

但是当一个对象实例被销毁时会发生什么?即使在工作线程完成后对象被销毁,也会从主线程调用iVector的析构函数。这会导致不确定的行为吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

首先,我建议在析构函数的线程上运行std::join(或等效的库)。这将确保在向量析构函数运行之前正确完成并同步线程。这很重要,因为向量的生命周期必须超过使用它的线程。

C ++ 11标准,可能是后来的30.3.1.5中的状态:

  

5:同步:完成由* this表示的线程   与(1.10)同步成功的join()返回。 [   注意:* this上的操作不同步。 - 结束说明]

现在我们必须检查1.10以获取更多细节,首先是本节说明:

  

3:特定点处线程T可见的对象的值   是对象的初始值,是由对象分配的值   T,或由另一个线程分配给该对象的值,根据   以下规则。

老实说,这很难解析,它没有详细说明连接提供什么样的同步,似乎暗示它只同步线程本身而不是它已访问的数据。因此,我会在加入主线程后运行atomic_thread_fence(memory_order_acquire)并在子线程完成之前运行atomic_thread_fence(memory_order_release),这应该保证在语义之前完全发生并且没有UB。

答案 1 :(得分:2)

如果执行线程正在使用ivector类成员,而另一个线程使用此类成员销毁该对象,则继续使用ivector类成员会导致未定义的行为。

  

即使在工作线程完成后对象被销毁,   将从主线程调用iVector的析构函数。将   这导致了未定义的行为?

没有。正如您所描述的,这种情况并非未定义的行为。 C ++标准不要求对象被创建对象的同一执行线程销毁。一个执行线程增长,调整向量大小,然后消失或停止使用向量,然后一个不同的执行线程破坏整个对象,这很好。