2009-10-06 9 views
31

私は、状態(単純な列挙型)を持ち、2つのスレッドからアクセスされるクラスを持っています。状態を変更するために、私はmutex(boost :: mutex)を使用します。状態を確認するのは安全ですか(たとえばstate_ == ESTABLISHEDを比較)、この場合もmutexを使用する必要がありますか?言い換えれば、別のスレッドが同時に書き込むことができる変数を読みたいだけの場合は、ミューテックスが必要ですか?読み込みにはミューテックスが必要ですか?

答えて

3

はい。スレッドbがスレッドbに書き込んでいる間にスレッドaが変数を読み込むと、未定義の値を読み取ることができます。読み取りと書き込みの操作は、特にマルチプロセッサシステムでは不可分ではありません。

+0

ライタースレッドが(fetch-> write-> store)している間に、読者が前回または後のいずれかの未定義値をフェッチするときに、私は見ませんが、未定義ではありません。 –

+0

1つの命令で読み込まれる列挙型の値を考慮に入れます。 –

+1

@Arkaitz:undefinedはおそらく正しい言葉ではありませんでした。しかし、CPU /メモリー・アーキテクチャーは、キャッシュの追加レベル、遅延の増加などによりますます複雑になります。答えは簡単です。いいえ!データの共有をロックフリーにします。専門家でさえこの分野で多くの間違いを犯します。 – sellibitze

0

変数が "volatile"で宣言されている場合は、一般的に言えません。それが単一の変数である場合にのみ、そうでなければ可能なレースについて本当に注意する必要があります。

+0

なぜあなたは揮発性の問題を考えるのですか? – jalf

+1

@jalf:volatileは、コードに変数の古いコピーが表示されるような最適化を実行しないようにコンパイラに指示します。 –

+2

しかし、問題は失効したコピーではありませんでした。変数がvolatileでなくても、遅かれ早かれ書き込まれます。これはボラティリティに関係なくアトミックになり、volatileはロード/ストアの並べ替えを妨げません。揮発性は実際にあなたに何も買わないこの場合。それは解決する必要がある問題を解決するものではなく、とにかく解決された問題を解決します。 – jalf

0

列挙型(読み取りまたは書き込み)へのアクセスを守る必要があります。

別のもの: スレッドの競合が少なく、スレッドが同じプロセスに属している場合、クリティカルセクションはミューテックスより優れています。

8

あなたは2つのスレッドを持っています。それらは情報を交換します。はい、ミューテックスが必要です。おそらくは条件付き待機も必要です。

あなたの例(compare state_ == ESTABLISHED)は、スレッド#2がスレッド#1が接続/状態を開始するのを待っていることを示しています。ミューテックスや条件文/イベントがなければ、スレッド#2はステータスを継続的にポーリングする必要があります。

スレッドは、パフォーマンスを向上させる(または応答性を向上させる)ために使用されます。通常、ポーリングは、多くのCPUを消費するか、またはポーリング間隔のために潜在性を導入することによってパフォーマンスを低下させます。

+0

+1は条件変数を提案します。そのサウンドから、彼は別の変更によって状態変化に応答する必要のあるスレッドを持っています。その場合、条件変数はもっと適切です。 – Falaina

+0

@Ermelli忙しいウェイトループを使用したいのであれば、mutexが必要です(ループで何か別の処理が行われる可能性があります) – Nick

0

実際には、読み取りのためにオブジェクトへのアクセスをロックする理由はありません。あなたはそれを書いている間だけそれをロックしたい。これはまさにリーダライターのロックです。書き込み操作がない限り、オブジェクトをロックしません。パフォーマンスが向上し、デッドロックが防止されます。より精巧な説明については、以下のリンクを参照してください。それが依存

wikipedia codeproject

12

C++言語は、スレッドまたはアトミック性については何も言いません。

最新のCPUでは、整数を読み取ることはアトミックな操作です。つまり、ミューテックスなしでも常に一貫した値を読み取ることができます。ミューテックス、または同期の他のいくつかの形式ずに、コンパイラとCPUが並べ替えることは自由ですが

は、読み込みと書き込み、その複数の変数にアクセス関わるものより複雑な、何が、まだ一般的なケースでは安全ではありません。

ライタースレッドがいくつかのデータを更新し、データが使用可能であることを他のスレッドに知らせるために整数フラグを設定すると、これは並べ替えることができるため、に設定してからデータを更新します。ミューテックスまたは別の形式のメモリバリアを使用していない限り。

正しい動作をしたい場合は、そのようなミューテックスは必要ありません。読み込み中に他のスレッドが変数に書き込む場合は問題ありません。あなたが非常に珍しいCPUで作業しているのでなければ、原子的になるでしょう。しかし、あなたはを実行するは、コンパイラやCPUで並べ替えを防ぐために何らかの種類のメモリバリアが必要です。

+0

volatileを指定しない限り、読み書きは実行されない可能性があります。遅かれ早かれ十分ではありません。 – EFraim

+3

しかし、揮発性であっても、CPUまたはコンパイラは書き込みを並べ替えることができ、無意味になります。正しい解決策はメモリの障壁です。そして、揮発性は単に不必要な最適化解除にすぎません。 – jalf

+0

@jalf:いいえ、フラグが1つだけ必要な場合は、いいえ。質問をもう一度読む。 – EFraim

関連する問題