我在Windows中使用Interlocked函數做了一個非常簡單的自旋鎖,並在雙核CPU上進行了測試(兩個線程遞增了一個變量)。英特爾Inspector報告我的自旋鎖實現中的數據競爭
程序似乎工作正常(它提供了相同的結果每一次,這是不是在沒有使用同步的情況下),但英特爾Parallel Inspector中說有在值+ = 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不能再被使用(該類還有一個可以自動釋放鎖的析構函數)。我想,我嘗試了你所說的,並且它是一樣的:程序正常工作,但英特爾Parallel Inspector表示存在競爭狀況。也許檢查員有一個錯誤?但可能不會:( – 2009-09-24 10:38:40
你也應該用長開始,而不是做明確的轉換,並在構造函數不帶參數,只是啓動它解鎖。如果創建它所需要的東西有它鎖定,首先,他們可以只創建後但在共享之前鎖定@Igratian - 你不需要RAII在這種情況下,由於析構函數無關清理(它只是一個長) – 2009-09-24 13:31:52
編輯。不會麻煩添加解構器......因爲這個問題不能完全糾正他的代碼。我只是想解決他的問題。 – Goz 2009-09-24 13:56:48