0

マルチスレッドプログラムで次のコードを検討してください。

    QString target = remaining.first(); // remaining is a QVector<QString> class
    remaining.pop_front();

安全でしょうか?複数のスレッドが同じ「ターゲット」を同時に使用しているようです。または、最初の値を取得して消去する安全な方法は何ですか?

4

1 に答える 1

2

そのコードを保護するミューテックスがなければ、いや、それはまったく安全ではありません。

詳細はわかりませんがQVector、2つのスレッドで両方を実行しても問題ないと思います。

QString target = remaining.first();

QStringこれは単にベクトルの要素をコピーするので、各スレッドには呼び出される独自のオブジェクトがtargetあり、それらは独立したオブジェクトです(舞台裏では暗黙の共有を使用するため、独立していませんが、独立したものとして扱うことができるはずです)

しかし、この行は:を変更しQVectorます

remaining.pop_front();

これは、2つのスレッドが同期せずに同じオブジェクトを変更することを意味します。remaining.first()2番目のスレッドが呼び出すときに最初のスレッドがまだ呼び出しによってベクトルにアクセスしている場合pop_front()は、未定義の動作を伴うデータ競合が発生します。

同様に、両方のスレッドがpop_front()同時に呼び出す場合、両方が最初の要素を削除しようとしますが、そこで何が起こるかは完全に予測できません。1つ、2つ、またはまったく消去しないか、プログラム全体をすぐにクラッシュさせる可能性があります。別の可能性として、ベクトルに要素が1つしかない場合にどうなるかを考えてみましょう。両方のスレッドは、それが空でないことを確認し、first()要素をコピーしてから、を呼び出しますpop_front()。これは、要素が1つしかない場合に2つの要素を削除しようとします。あなたはプログラムが壊れています。

これを行うための安全な方法は、ミューテックスでコードを保護することです。ミューテックスでmutexは、両方のスレッドに表示されるグローバル変数または共有変数があります。

QString target;
{
  QMutexLocker locker(&mutex);
  if (!remaining.empty())
  {
    target = remaining.first();
    remaining.pop_front();
  }
}
于 2012-10-18T16:37:09.847 に答える