2

複数のスレッドが同じオブジェクトへのポインターを共有している場合、その仮想メソッドを呼び出しても安全ですか?もちろん、メソッド自体はスレッドセーフであると想定する必要があります。

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

5 に答える 5

2

はい、オブジェクトの有効期間が*base関数呼び出しの有効期間を超えていれば問題ありません。

于 2013-02-07T14:29:50.783 に答える
1

「前の回答に対するKerrekSBのコメントに基づいて、この回答を約3回開始しました。仕様を読まずに、目が出血するまで、何がスレッドセーフであってはならないのかわかりません。呼び出し-「仮想関数選択」(vtableまたはそれが何であれ)の実装は、関数へのポインターである必要があるため、間違いなく問題を引き起こさないはずです。これは、のインデックス[または同様のもの]に基づいて呼び出されます。選択された関数。

申し訳ありませんが、これは答えではありませんが、どのプロセッサでも、それがどのように機能するかを知っているので、シナリオを見るのは非常に困難です(x86、68K、29k、ARMは私が十分に取り組んできたものです仮想関数がアセンブラーでどのように実装されているかを理解してください)スレッドが原因でこれがうまくいかない場合(他のコードが安全であると仮定して)上記の例で、どの要素がbase指すかを変更する2番目のスレッドを実行すると、 baseの値が間違った仮想関数のセットなどを指している、一種の競合状態。しかし、それは呼び出し自体ではなく、base「スレッドセーフではない」コード変更です。

もちろん、他の方法で仮想関数を解決する「アマチュア」コンパイラが周りにあるかもしれません。

もちろん、問題が発生した場合(仮想呼び出しの全期間にわたって他のスレッドをブロックしない限り)、および仮想関数run(void *args)を「this」として持つことによってスレッドを実装するクラスがある場合は、賢明な回避策はありません。スレッド内で実行するものです」これは私が何度か見たものですが、それはその機能を完全に破壊するでしょう!

ですから、基本的には、これは安全だというスペックのセクションを参照することはできませんが、「そうしなければならない」以外の解決策は見当たりません。

于 2013-02-07T14:49:22.473 に答える
1

仮想関数の呼び出しは、通常、クラス内の vtable エントリを検索することによって実装されます。この vtable は変更されないため、この実装ではスレッド セーフにする必要があります。

一般的な保証はないと思います。

于 2013-02-07T14:30:57.120 に答える
0

要するに、そうでなければ、C++ はマルチスレッド プログラミングにまったく使用できません。

長文:

  1. コンパイル後、プログラムは一定です。したがって、スレッドセーフです。

  2. (モジュールの) ロード中に、ランタイム システムは RTTI (dynamic_cast など) のデータ構造を変更します。これはあなたの範囲外ですが、スレッドセーフな方法で実装する必要があります。

  3. 構築後、オブジェクトのタイプは変更されません (非常に汚いトリックで変更できます)。したがって、すべてのオブジェクトのすべての仮想関数は変更されるべきではありません。したがって、スレッドセーフです。

ただし、仮想関数 (boost 関数、loki functor など) の代替と見なすことができるクラスのメンバーには、値のセマンティクスがあり、呼び出し中に変更される可能性があることを考慮する必要があります。この場合、文書化するか、それらを使用するためのより良いインターフェイスを実装する必要があります。

私の意見では、仮想メソッドを安全に呼び出すことができます。誰かが仮想機能を模倣しようとした場合でも、通常の (安全な) 動作を期待できます。

于 2013-02-07T15:14:56.037 に答える
0

メソッドがスレッドセーフであれば問題ありません。

于 2013-02-07T14:31:16.457 に答える