Ho creato uno spinlock molto semplice utilizzando le funzioni Interlocked in Windows e testato su una CPU dual-core (due thread che incrementano una variabile);Intel Inspector segnala una corsa di dati nella mia implementazione di spinlock
Il programma sembra funzionare bene (dà lo stesso risultato ogni volta, che non è il caso in cui non viene utilizzato alcun la sincronizzazione), ma Intel Parallel Inspector dice che c'è una condizione di competizione al valore + = j (vedere il codice sotto). L'avviso scompare quando si utilizzano le sezioni critiche anziché il mio SpinLock.
La mia implementazione di SpinLock è corretta o no? È davvero strano, perché tutte le operazioni usate sono atomiche e hanno le appropriate barriere di memoria e non dovrebbero portare a condizioni di gara.
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); }
};
Il programma di test:
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;
}
Quello che vi proposto è di circa lo stesso con quello che faccio, solo che l'int intorno il blocco degli spin è contenuto nella classe ... e questo sarebbe uno svantaggio, perché RAII non può più essere usato (la classe ha anche un distruttore che rilascia automaticamente il blocco). Pensavo, ho provato quello che hai detto, ed è lo stesso: il programma funziona correttamente, ma Intel Parallel Inspector dice che c'è una condizione di competizione. Forse l'ispettore ha un bug? Ma probabilmente no :( –
dovresti anche usare molto tempo per iniziare invece di fare il cast esplicito, e nel costruttore non prendere parametri e solo avviarlo sbloccato.Se la cosa che lo ha creato deve averlo bloccato per cominciare, possono solo bloccalo dopo averlo creato ma prima di condividerlo. @Igratian - In questo caso non hai bisogno di RAII dato che il distruttore non ha nulla da pulire (è solo un lungo). –
Modificato.Non mi preoccuperò di aggiungere il decostruttore ... poiché la domanda non garantisce la totale correzione del suo codice. Stavo solo cercando di risolvere il suo problema. – Goz