J'ai fait un spinlock très simple en utilisant les fonctions Interlocked dans Windows et l'ai testé sur un CPU dual-core (deux threads qui incrémentent une variable);Intel Inspector signale une course de données dans mon implémentation de spinlock
Le programme semble fonctionner OK (il donne le même résultat à chaque fois, ce qui est le cas en l'absence de synchronisation est utilisé), mais Intel Parallel Inspector dit qu'il ya une condition de course à valeur + = j (voir le code ci-dessous). L'avertissement disparaît lorsque vous utilisez des sections critiques au lieu de SpinLock.
Mon implémentation de SpinLock est-elle correcte ou non? C'est vraiment étrange, parce que toutes les opérations utilisées sont atomiques et ont les barrières de mémoire appropriées et cela ne devrait pas conduire à des conditions de course.
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); }
};
Le programme d'essai:
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;
}
Ce que vous proposez est de la même chose avec ce que je fais, seulement que l'int autour les spins de verrouillage sont contenus dans la classe ... et ce serait un inconvénient, car RAII ne peut plus être utilisé (la classe a aussi un destructeur qui libère automatiquement le verrou). J'ai pensé, j'ai essayé ce que vous avez dit, et c'est la même chose: le programme fonctionne correctement, mais Intel Parallel Inspector dit qu'il y a une condition de concurrence. Peut-être que l'inspecteur a un bug? Mais probablement pas :( –
vous devriez également utiliser long pour commencer au lieu de faire la distribution explicite, et dans le constructeur ne prennent pas de paramètres et commencent juste à le déverrouiller.Si la chose qui le crée a besoin d'être verrouillé pour commencer, ils peuvent juste verrouillez-le après l'avoir créé mais avant de le partager. @Igratian - Vous n'avez pas besoin de RAII dans ce cas puisque le destructeur n'a rien à nettoyer (c'est juste un long) –
Edited.Ça ne dérange pas d'ajouter le déconstructeur ... car la question ne justifie pas de corriger totalement son code. J'essayais juste de résoudre son problème. – Goz