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