虚方法调用是否是线程安全的?

时间:2013-02-07 14:26:26

标签: c++ thread-safety

如果多个线程共享指向同一对象的指针,调用其虚方法是否安全?当然,我们应该假设该方法本身是线程安全的。

class Base {
public:
  virtual int test(int arg) = 0;
};

class Derived1: public Base {
public:
  virtual int test(int arg) { return arg * 2; }
};

class Derived2: public Base {
public:
  virtual int test(int arg) { return arg * 3; }
};

//call in threads:
Base* base = (pointer to the same Derived1);
int value = base->test(1);

5 个答案:

答案 0 :(得分:1)

是的,如果对象*base的生命周期超过函数调用的生命周期,那很好。

答案 1 :(得分:1)

通常通过在类中查找vtable条目来实现调用虚函数。此vtable不会更改,因此对于此实现,它应该是线程安全的。

我认为没有一般保证。

答案 2 :(得分:1)

我已经开始这个答案大约三次了,基于“Kerrek SB对前一个答案的评论。我看到它,没有阅读规格,直到我的眼睛流血,我不确定什么不应该线程安全一个虚拟调用的实现 - “虚函数选择”(vtable或它可能是什么)的实现绝对不应该引起任何问题,因为它应该只是一个指向函数的指针,它根据索引[或类似的方式调用] ]选择的功能。

对不起,这不是一个答案,但我很难看到任何情况,在我知道它如何工作的任何处理器上(x86,68K,29k,ARM是我工作的那些足以了解如何在汇编程序中实现虚函数)这会因为线程而出错 - 假设其他代码是安全的 - 如果在上面的示例中我们运行第二个线程来修改哪个元素base指出,您可能会遇到某种竞争条件,其中base的值指向错误的虚函数集,或者其中一些。但这不是调用本身,而是修改base的代码,即“非线程安全”。

当然,可能会有一些“业余”编译器以其他方式解决虚函数问题。

当然,没有合理的解决方法,如果有问题 - 除非你在整个虚拟调用期间阻塞其他线程 - 并且你有一个通过拥有虚函数来实现线程的类{ {1}}因为“这就是在线程中运行的东西”,这是我多次见过的东西,它几乎完全杀掉了这个功能!

所以,基本上,虽然我无法参考说明这是安全的规范部分,但除了“必须”之外,我看不到任何解决方案。

答案 3 :(得分:0)

如果方法是线程安全的,那就没关系了。

答案 4 :(得分:0)

简而言之: 如果没有,C ++根本不可用于多线程编程。

长期:

  1. 编译后程序是不变的。所以它的线程安全。

  2. 在加载(模块)时,运行时系统会更改数据结构 RTTI(dynamic_cast,...)。这超出了您的范围,但应该以线程安全的方式实现。

  3. 构建后,对象的类型不会改变(你可以使用非常肮脏的技巧)。因此,所有对象的所有虚拟功能都不应更改。所以它的线程安全。

  4. 但你应该考虑可以被视为虚函数替换的类成员(boost函数,loki函子,......)可能具有值语义,并且可以在调用时进行更改。在这种情况下,应该记录它,或者应该实现更好的使用它们的界面。

    在我看来,你可以安全地调用虚拟方法。即使在有人使用模拟虚拟函数的情况下,你也可以期待正常(安全)的行为。