Zrobiłem bardzo prosty spinlock za pomocą funkcji powiązanych w Windows i przetestowałem go na dwurdzeniowym procesorze (dwa wątki, które zwiększają zmienną);Intel Inspektor raportuje wyścig danych w mojej implementacji spinlock
Program wydaje się działać OK (daje ten sam wynik za każdym razem, co nie jest w przypadku, gdy nie jest używany do synchronizacji), ale Intel Parallel Inspector mówi, że istnieje sytuacja wyścigu w wartości + = j (patrz poniższy kod). Ostrzeżenie znika podczas używania Sekcji krytycznych zamiast mojego SpinLocka.
Czy moja implementacja SpinLock jest poprawna czy nie? To naprawdę dziwne, ponieważ wszystkie używane operacje są atomowe i mają odpowiednie bariery pamięciowe i nie powinny prowadzić do warunków wyścigowych.
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); }
};
Program testowy:
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;
}
Co proponowana jest o tym samym co ja, tylko że int wokół spiny blokady są zawarte w klasie ... i byłoby to wadą, ponieważ nie można już używać RAII (klasa ma również destruktor, który automatycznie zwalnia blokadę). Pomyślałem, próbowałem tego, co powiedziałeś, i to jest to samo: program działa poprawnie, ale Intel Parallel Inspector mówi, że istnieje stan wyścigu. Może inspektor ma błąd? Ale prawdopodobnie nie :(od –
powinieneś także użyć długiego na początku, zamiast wykonywać wyraźną obsadę, aw konstruktorze nie pobierać żadnych parametrów i po prostu uruchamiać go odblokowany .Jeżeli stworzenie to musi mieć zablokowane na początek, mogą po prostu zablokuj go po utworzeniu, ale przed udostępnieniem go. @Illian - W tym przypadku nie potrzebujesz RAII, ponieważ destruktor nie ma nic do wyczyszczenia (jest tylko długi) –
Edytowany.Nie zawracaj sobie głowy dodawaniem dekonstruktora ... ponieważ to pytanie nie gwarantuje całkowitej korekty jego kodu. Próbowałem tylko rozwiązać jego problem. – Goz