-1
std::deque<T> dq;
Thread_function(pointer to queue as argument)     // created 8 threads
{
     vertext_found = true;
     **v is initialized to NULL
     while ( i < dq->size())
     {
          EnterCriticalSection(&h);
          if( i < dq.size() ) {
              v = dq.at(i);      // accessing element of queue without popping
              i++;
              vertext_found = true;
          }
          LeaveCriticalSection(&h);
          if (vertext_found && (i < dq.size()) && v != NULL)
          {
              **operation on 'v'
              vertext_found = false;
          }
     }
}

特にクリティカル セクションの外側で" while ( i < dq->size()) " を処理する場合、これはデータ競合状態になりますか? 私のアプローチは正しいですか?それ以外の場合は、私に提案してください。

4

1 に答える 1

4

これはマルチスレッド環境で非干渉になりますか?

質問のテキストでは、dq(関数内の他のすべての変数と同様に)ローカルオブジェクトです。

std::deque<T> dq;

これが本当に当てはまる場合、質問の答えは簡単です: 「はい」 . 競合がないため、スレッドセーフです。各スレッドはローカル オブジェクトで動作し、共有がないため、データ競合が発生することはありません。


あなたのコードが共有データ構造の使用を示すことを意図しており、それdqが実際にはグローバルオブジェクトか、何らかの方法で複数のスレッドから同時にアクセスできるものであると仮定すると (これはdq->size()関数呼び出しが示唆しているように見えます)、答えは「依存します」です。 " .

すべてのスレッドが、表示している関数のみを同時に実行していてdq、 への参照またはポインターでconstconstあり、関数に非メンバー関数への呼び出しが含まれていない場合、答えは「はい、しかし、この場合、クリティカルセクションはまったく必要ありません。」パラグラフ 17. C++11 標準の 6.5.9/3 では、次のように指定されています。

const C++ 標準ライブラリ関数は、現在のスレッド以外のスレッドからアクセス可能なオブジェクト (1.10) を直接的または間接的に変更してはなりませんthis

データ競合とは何かを定義するパラグラフ 1.10 (特に 1.10/21) への参照は、上記のパラグラフの意味をより明確にします。

プログラムの実行にデータ競合が含まれているのは、異なるスレッドに競合する 2 つのアクションが含まれており、そのうちの少なくとも 1 つがアトミックではなく、どちらも他のスレッドの前に発生しない場合です。このようなデータ競合は、未定義の動作を引き起こします。[...]

最後に、パラグラフ 1.10/4 は、2 つのアクションが競合する場合を指定します。

2 つの式の評価は、一方がメモリ ロケーション (1.7) を変更し、もう一方が同じメモリ ロケーションにアクセスまたは変更する場合に競合します。

これらすべてから、constメンバー関数は必然的にスレッドセーフであることがわかりますHerb Sutter によるこのプレゼンテーションをご覧になることをお勧めします。

deque<T>::size()constメンバ関数であり、はat()への参照を返すconstメンバ関数 ( への参照またはポインタから呼び出しているため) であるため、複数のスレッドからのアクセスを同期する必要はありません。constconst


yourdqがへの参照またはポインターでないconst場合、 は非メンバー関数であるため、答えは「いいえ」です。さらに、は要素への非 const 参照であるため、「操作」は non- になる可能性があり、それ自体ではなくの要素にデータ競合が発生します。at()constvvconstdqdq

同様に、スレッドが同時にdq他の関数にアクセスして変更している場合、共有オブジェクトへのすべてのアクセスを保護しているわけではないため、答えはやはり「いいえ」です。読み取り操作は書き込み操作と競合し (上記を参照)、それらの一部のみを保護しています。この場合、クリティカル セクションはwhileサイクル全体にまたがる必要があります。

于 2013-03-10T18:10:13.150 に答える