2

インクリメント/デクリメントする複数のスレッドからアクセスされるカウンター変数があります。複数のスレッドで同時に更新しないでください。

問題の変数を変更する前に取得する必要のあるミューテックスオブジェクトを作成できることを私は知っています。問題の変数を変更できる関数が複数あるため、この場合のクリティカルセクションは適切ではありません。

ミューテックスを使用せずにこれを実行できる別の方法はありますか?ミューテックスを使用すると、パフォーマンスが低下します(http://www.codeguru.com/forum/showthread.php?t=333192を参照)。Javaには、それを実現するために変数宣言で使用できるキーワードがあると思いますが(「同期」と呼ばれますか?)、C ++にはそのようなものがありますか?

volatileは私が探しているキーワードではないことを私は知っています。

どうもありがとうございます。

4

8 に答える 8

8

ほとんどのプロセッサには、「アトミック」インクリメントおよびデクリメント命令があります。大部分は、ミューテックスがマシンレベルで実装される方法です。

これらのアトミック命令には、独自のコードでアクセスできます。WindowsはInterlockedIncrement()関数を提供し、glibは同等のものを提供します。x86アセンブリ言語では、LOCK CMPXCHG直接使用して親族化することができます。

C ++はこれらの概念について何も知りません。つまり、自分で使用する必要があります。C++にはスレッドセーフのための魔法のキーワードはありません。

アトミックインストラクションを参照してください

于 2010-01-28T12:53:35.310 に答える
4

アトミック操作の使用はおそらく最も効率的ですが、これが複数の関数で使用されているという事実は、このコードまたは他のコードでクリティカルセクションを使用することを妨げるものではありません-単に関数を記述してください:

void IncDec( bool inc ) {
   EnterCritical Section( theCS );
   if ( inc ) {
     theVar++;
   }
   else {
     thevar--;
   }
   LeaveCriticalSection( theCS );
}

他の関数から計算します。

于 2010-01-28T12:59:45.967 に答える
3

説明から、 InterlockedIncrementと関連するデクリメント関数だけが必要なようです。

編集-これらはWindowsの機能です...私はどのプラットフォームを尋ねるのをやめませんでした。

于 2010-01-28T12:53:04.023 に答える
3

問題の変数を変更できる関数が複数あるため、この場合のクリティカルセクションは適切ではありません。

これはクリティカルセクションが使用される一般的なシナリオです。同じクリティカルセクション(またはミューテックス、または使用されているガード)に入るときに、変数にアクセスするすべてのコードがアクセスすることを保証する必要があります。

于 2010-01-28T13:01:24.237 に答える
2

Win32では、IntelockedIncrement / IntelockedIncrement64および関連する操作は、32ビットワードまたは64ビットワード(アーキテクチャに応じて)でプロセッサレベルのアトミック操作を可能にするx86命令にコンパイルされます。これは単純なカウンターの場合は正常に機能しますが、より大きな構造を複数の単語と同期させようとすると当然機能しません。

ここからのPS 、対応するasmは、x86で実行されているWin32以外のシステムにこれを実装する必要があります。

inline long InterlockedExchangeAdd( long* Addend, long Increment )
{
long ret;
__asm__ (
/* lock for SMP systems */
"lock\n\t"
"xaddl %0,(%1)"
:"=r" (ret)
:"r" (Addend), "0" (Increment)
:"memory" );
return ret;
}

inline long InterlockedIncrement( long* Addend )
{
return InterlockedExchangeAdd( Addend, 1 );
}

inline long InterlockedDecrement( long* Addend )
{
return InterlockedExchangeAdd( Addend, -1 );
}
于 2010-01-28T12:59:15.910 に答える
0

他の人が述べているように、現在のC ++標準には、アトミック変数アクセスをサポートするものはありません。ただし、C ++ライブラリのサポートを求めている場合(私には完全には明らかではありません)、ここで、今後のC++標準のアトミックサポートを模倣する試みが進行中です

于 2010-01-28T14:19:41.750 に答える
0

カウンター変数にアトミックタイプを使用できます-sig_atomic_t(GNU libc内)のように。その場合、同期の必要はありません。競合状態が発生する可能性がないため、この変数の操作はアトミックであることが保証されます。

于 2010-01-28T12:58:31.307 に答える
0

問題の変数を変更できる関数が複数あるため、この場合のクリティカルセクションは適切ではありません。

クリティカルセクションを使用して変数を変更する単一の関数を作成しない場合、変数がアクセスできる可能性のあるすべての場所を見つけたことをどのようにして知ることができますか?

さらに、コンパイラが変数へのアクセスを誤って最適化しないように、変数volatileを宣言する必要があります。

于 2010-01-28T14:36:27.103 に答える