我有一个多态对象o
和两个帖子T1
和T2
。
o
派生类的析构函数在返回之前等待T2
的终止。
在T1
调用o
的某些虚拟函数时,让T2
删除o
是否安全? (我的意思是不使用互斥或任何其他类型的同步机制)
我相信它应该是安全的,除非delete
被允许修改o
(就像它指向vtable的指针),甚至在第一个析构函数被调用完成之前。是这种情况吗?
答案 0 :(得分:2)
首先,如果你可以避免这种情况,那就很脆弱且容易出错。你可以使它工作,但代码中的细微变化可能会破坏它。
如果完整对象析构函数中的块唯一做的是等待另一个线程的完成,并假设基础对象具有虚拟析构函数或者直接销毁整个对象,则然后这是安全这样做。在析构函数的主体完成之前,对象的所有成员都不会被销毁,也不是基础。这意味着另一个线程正在使用的子对象都不会在它完成之前被销毁(并让第一个线程完成析构函数的主体)。
话虽如此,再次尝试重新设计代码。
答案 1 :(得分:0)
想象一下你的班级有一些动态分配成员的场景,
T1
的析构函数可能会在T2
仍然访问这些成员时解除分配这些成员。
这将导致未定义的行为。
只要你能确保T1
的析构函数和T2
的函数不在同一个成员上运行就是安全的,但是如果你不能确保它,那么你肯定需要一些同步。
请注意,基本逻辑保持不变,没有两个线程可以在同一实体上同时读写,否则最终会出现竞争条件和同步问题。
答案 2 :(得分:0)
如上所述,这是有风险的,但您可以采取一些措施来降低风险。线程同步的责任应该是派生程度最高的类的唯一责任。特别是,除了析构函数之外,这个派生类最多的类不应该有任何虚函数。
这种设计意味着T2不能在最派生的类中调用任何函数。它最多可以依赖于o
基类的成员,并且这些成员将在最大派生的dtor返回之前有效 - 这将在T2退出之后。这意味着以下序列不会被重新排序,除了可能的步骤2和3(无害)
T2
可以访问o
T1
中,输入了o
的dtor T2
退出。T1
中,o
的dtor返回o
的基类方法。