0

この関数のネーミングは、複雑なことが起こっているようです。次のようなことをする代わりに、これが進むべき道であることを正確に知るのはいつですか:

準備 CRITICAL_SECTION cs; int *p = malloc(sizeof(int)); // 割り当てサイト InitializeCriticalSection(&cs); // 最初の書き込みのヒント

スレッド #1 { *p = 1; // 最初の書き込み }

スレッド #2 { EnterCriticalSection(&cs); *p = 2; // 2 回目の書き込み LeaveCriticalSection(&cs); }

1 つのスレッドで実行される書き込みがあります。

Run()
{
// some code
m_bIsTerminated = TRUE;
// some more code
}

次に、別のスレッドで行われる読み取りがあります (同時に行われる可能性があります)。

Terminate()
{
// some code
if( m_bIsTerminated )
{
m_dwThreadId = 0;
m_hThread = NULL;
m_evExit.SetEvent();
return;
}
// even more code
}

この競合状態を解決するための最良の解決策は何ですか? クリティカル セクションを使用するか、InterlockedExchangeAdd() を使用する方が便利ですか?

4

3 に答える 3

3

あなたの場合、競合状態はありません。変数が FALSE にリセットされることはありませんね。スレッドの「死んでください」スイッチですよね?その後、いかなる種類の同期も必要ありません。

関数の InterlockedXXX ファミリは、Intel CPU のアトミック 3 オペランド コマンド (XADD および CMPXCNG) を利用します。そのため、クリティカル セクションよりもはるかに安価です。そして、スレッドセーフな割り当てに必要なものは InterlockedCompareExchange() です。

UPD: 変数を揮発性としてマークします。

于 2010-01-14T22:02:51.723 に答える
0

m_bIsTerminated が揮発性としてマークされていることを確認してください。問題ありません。// "is terminate" を true に設定した後にさらにコードを追加するのはかなり奇妙に思えますが。その変数は正確に何を示していますか?

あなたの「競合状態」は、 // more コードのさまざまな要素が異なる順序で実行できることです。あなたの変数はそれを助けません。それらを決定論的な順序で実行させることがあなたの目標ですか? はいの場合、あるスレッドで待機し、別のスレッドで設定する条件変数が必要です。それらを同時に実行したくない場合は、クリティカルセクションで問題ありません。

于 2010-01-14T22:11:53.710 に答える
0

InterlockedExchangeAdd は、アトミック操作として整数に値を追加するために使用されます。つまり、クリティカル セクションを使用する必要はありません。これにより、スレッドの 1 つが例外をスローした場合のデッドロックのリスクも排除されます。他のスレッドがそのロックを取得できなくなるため、いかなる種類のロックも保持しないようにする必要があります。

あなたのシナリオでは、間違いなく Interlocked...- 関数を使用できますが、イベント (CreateEvent、SetEvent、WaitForSingleObject) を使用します。おそらく、複数のオブジェクトを待機する必要があることが多いためです (ゼロ秒待機できます)あなたのシナリオで)。

Upd: 変数に volatile を使用すると機能する場合がありますが、推奨されません。次を参照してください: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.htmlおよびhttp:/ /www-949.ibm.com/software/rational/cafe/blogs/ccpp-parallel-multicore/tags/c%2B%2B0xなど。

移植可能にしたい場合は、boost::threadを見てください。

于 2010-01-14T22:17:15.233 に答える