Виртуальный метод называется потокобезопасным?

Если несколько потоков совместно используют указатель на один и тот же объект, безопасно ли вызывать его виртуальный метод? Конечно, мы должны предположить, что сам метод является потокобезопасным.

```
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);

```

Да, это нормально, если срок службы объекта  `* base`  превышает срок службы вызова функции.



Я начал этот ответ примерно три раза, основываясь на комментарии «Kerrek SB» по предыдущему ответу. Как я вижу, без чтения спецификаций, пока мои глаза не истекают кровью, я не уверен, что не должно быть поточным виртуальным вызов - реализация «выбора виртуальных функций» (vtable или что-то еще, что может быть) должна определенно не вызвать никаких проблем, поскольку она должна быть просто указателем на функцию, которая вызывается на основе индекса [или аналогичного] функция выбрана.

Извините, это не ответ, но мне очень трудно увидеть любой сценарий на любом процессоре, который я знаю, как он работает (x86, 68K, 29k, ARM - это те, над которыми я работал достаточно, чтобы понять, как виртуальная функция реализована на ассемблере), где это пойдет не так из-за потоков - если другой код будет безопасным - если в приведенном выше примере мы должны были запустить второй поток, который изменяет какой элемент  `base`  точки, вы могли бы иметь какое-то гоночное состояние, где значение базы указывает на неправильный набор виртуальных функций или на некоторые из них. Но это не сам вызов, а код, изменяющий  `base` , который не является потокобезопасным.

Конечно, может быть некоторый «любительский» компилятор, который решает виртуальные функции каким-то другим способом.

Разумеется, не было бы разумного обходного пути, если бы была проблема - если только вы не блокируете другие потоки в течение всего времени виртуального вызова, - и если у вас есть класс, который реализует потоки с помощью виртуальной функции  `run (void * args)`  как «это то, что нужно запускать внутри потока», что я уже несколько раз видел, и это полностью уничтожило бы эту функциональность!

Итак, в основном, хотя я не могу ссылаться на раздел спецификации, в котором говорится, что это безопасно, я не вижу никакого решения, кроме «он должен быть».



Вызов виртуальных функций обычно осуществляется путем поиска записи vtable в классе. Этот vtable не изменяется, поэтому для этой реализации он должен быть потокобезопасным.

Я не думаю, что есть общая гарантия.



Вкратце:
Если нет, C ++ не будет использоваться вообще для многопоточного программирования.

В долгосрочной перспективе:

1. После компиляции программа является постоянной. Так что его поток безопасен.
2. При загрузке (модулей) система времени выполнения изменяет структуры данных для
RTTI (dynamic\_cast, ...). Это выходит за рамки вашего приложения, но оно должно быть реализовано безопасным потоком.
3. После построения тип вашего объекта не изменяется (вы можете с очень грязными трюками). Таким образом, все виртуальные функции всех ваших объектов не должны меняться. Так что его поток безопасен.

Но вы должны учитывать, что член классов, который можно рассматривать как замену для виртуальных функций (функция boost, loki functor, ...), может иметь семантику значений и может меняться при вызове. В этом случае он должен быть документирован или лучше использовать интерфейс для их использования.

На мой взгляд, вы можете безопасно вызвать виртуальный метод. Даже в том случае, если кто-то использует попытки имитировать виртуальные функции, вы можете ожидать нормального (безопасного) поведения.



Если метод является потокобезопасным, то это нормально.