Ich machte einen sehr einfachen Spinlock mit den Interlocked-Funktionen in Windows und testete es auf einer Dual-Core-CPU (zwei Threads, die eine Variable inkrementieren);Intel Inspector meldet ein Datenrennen in meiner Spinlock-Implementierung
Das Programm scheint gut zu funktionieren (es gibt das gleiche Ergebnis jedes Mal, was nicht der Fall ist, wenn keine Synchronisation verwendet wird), aber Intel Parallel Inspector sagt, dass es eine Race-Bedingung + bei Wert = j (siehe Code unten). Die Warnung verschwindet, wenn kritische Abschnitte anstelle meines SpinLocks verwendet werden.
Ist meine Implementierung von SpinLock korrekt oder nicht? Es ist wirklich seltsam, denn alle verwendeten Operationen sind atomar und haben die richtigen Speicherbarrieren und es sollte nicht zu Rennbedingungen führen.
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); }
};
Das Testprogramm:
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;
}
Was Sie vorgeschlagen wird, ist ungefähr das Gleiche mit dem, was ich tun, nur, dass der int um Der Lock-Spins ist in der Klasse enthalten ... und das wäre ein Nachteil, weil RAII nicht mehr verwendet werden kann (die Klasse hat auch einen Destruktor, der die Sperre automatisch aufgibt). Dachte, ich habe versucht, was du gesagt hast, und es ist das gleiche: Das Programm funktioniert korrekt, aber Intel Parallel Inspector sagt, dass es eine Race Condition gibt. Vielleicht hat der Inspektor einen Fehler? Aber wahrscheinlich nicht :( –
sollten Sie auch lange verwenden, um mit dem expliziten Cast zu beginnen, und im Konstruktor nehmen Sie keine Parameter und starten Sie es nur entsperrt. Wenn das Ding es erstellen muss es zu Beginn gesperrt haben, können sie nur Sperren Sie es nach dem Erstellen, aber bevor Sie es teilen. @Igratian - Sie brauchen RAII in diesem Fall nicht, da der Destruktor nichts zu bereinigen hat (es ist nur eine lange). –
Edited.Ich werde mich nicht darum kümmern, den Dekonstruktor hinzuzufügen ... da die Frage nicht ausreicht, seinen Code vollständig zu korrigieren. Ich habe nur versucht, sein Problem zu lösen. – Goz