Windowsのインターロック機能を使用して非常に簡単なスピンロックを作成し、デュアルコアCPU(変数をインクリメントする2つのスレッド)でテストしました。Intel Inspectorはスピンロック実装のデータ競合を報告します
プログラムがOKを動作するようです(それは同じ結果に何の同期が使用されていない場合ではありませんたびに、与え)、しかしIntelはインスペクタが値+ = jでの競合状態があることを述べているパラレル(下記のコードを参照してください)。 SpinLockではなくクリティカルセクションを使用すると警告が消えます。
私のSpinLockの実装は正しいですか?使用されているすべての操作がアトミックで、適切なメモリ障壁があり、競合状態に陥らないため、実際には奇妙です。
class SpinLock
{
int *lockValue;
SpinLock(int *value) : lockValue(value) { }
void Lock() {
while(InterlockedCompareExchange((volatile LONG*)lockValue, 1, 0) != 0) {
WaitABit();
}
}
void Unlock() { InterlockedExchange((volatile LONG*)lockValue, 0); }
};
テストプログラム:
static const int THREADS = 2;
HANDLE completedEvents[THREADS];
int value = 0;
int lock = 0; // Global.
DWORD WINAPI TestThread(void *param) {
HANDLE completed = (HANDLE)param;
SpinLock testLock(&lock);
for(int i = 0;i < 1000*20; i++) {
for(int j = 0;j < 10*10; j++) {
// Add something to the variable.
testLock.Lock();
value += j;
testLock.Unlock();
}
}
SetEvent(completed);
}
int main() {
for(int i = 0; i < THREADS; i++) {
completedEvents[i] = CreateEvent(NULL, true, false, NULL);
}
for(int i = 0; i < THREADS; i++) {
DWORD id;
CreateThread(NULL, 0, TestThread, completedEvents[i], 0, &id);
}
WaitForMultipleObjects(THREADS, completedEvents, true, INFINITE);
cout<<value;
}
は、あなただけの周りのint型という、私は何をすべきかとほぼ同じである提案は何ロックスピンはクラスに含まれています...これは、RAIIはもはや使用できないので(クラスには自動的にロックを解除するデストラクタもあります)、不利になります。あなたが言ったことを試してみました。それは同じです。プログラムは正しく動作しますが、Intel Parallel Inspectorは競合状態があると言います。インスペクタにバグがありますか?しかし、おそらくそうではありません:( –
あなたはまた、明示的なキャストを行うのではなく、最初から始めるべきであり、コンストラクタでパラメータを取らず、ロックを解除して起動する必要があります。 @Igratian - この場合、デストラクタはクリーンアップするものがないので(ちょっと長い)、RAIIは必要ありません。 –
編集されました。デストラクタの追加を気にするつもりはありません。なぜなら、質問はコードを完全に修正することを保証するものではないからです。私はちょうど彼の問題を解決しようとしていた。 – Goz