2010-01-26 12 views
6

To robi moją głowę.G ++ CAS (__sync_val_compare_and_swap) Problem wymaga wyjaśnienia

Próbuję zaimplementować jakiś kod "lock-free" i używam CAS (gcc __sync_val_compare_and_swap) czynił dźwiganie ciężarów.

Mój problem można wyświetlić za pomocą następującego kodu.

volatile bool lock; 
void *locktest(void *arg) 
{ 
    for (int i = 0 ; i < 100000 ; ++i) 
    { 
     // acquire a lock 
     while(__sync_val_compare_and_swap(&lock, false, true) == true) 
     { 
      // Spin while we don't acquire 
     } 

     // make sure we have the lock 
     assert(lock == true); 

     // release the lock 
     assert(__sync_val_compare_and_swap(&lock, true, false) == true); 
    } 
} 

OK, jeśli uruchomię powyższy kod w 10 równoczesnych wątkach, wszystko będzie dobrze.

Jednakże, jeśli mogę zmienić kod, aby przeczytać

 // acquire a lock 
     while(__sync_val_compare_and_swap(&lock, lock, true) == true) 

Zawiadomienie Zmieniłem "false" na "lock".

rozpętuje się piekło i twierdzenie

 // make sure we have the lock 
     assert(lock == true); 

pożarów. Czy ktoś może wyjaśnić, dlaczego to robi różnicę?

Thx Oznacz.

Odpowiedz

5

Wygląda na to, że __sync_val_compare_and_swap zawsze zwróci starą wartość zmiennej, nawet jeśli nie doszło do zamiany. W takim przypadku załóżmy, że inny wątek blokuje blokadę tuż przed próbą jego pozyskania - wtedy lock jest prawdziwe i dzwonisz pod numer __sync_val_compare_and_swap(&lock, true, true);. Tuż przed faktycznym porównaniem i zamianą atomów (ale po określeniu argumentów funkcji) drugi wątek zwalnia blokadę - lock staje się fałszywy. compare_and_swap następnie zwróci wartość false, ale nie wykona operacji swap, ponieważ wartość, do której porównał, nie była wartością w zamku. Ten wątek nie wykonał zamiany, więc wartość lock pozostaje false, wyzwalając twoje potwierdzenie.

Nawiasem mówiąc, zdecydowanie sugeruję wykonanie lock a volatile bool. Nie chcesz, aby kompilator optymalizował odniesienia do takich zmiennych.

+0

Dzięki Aidan. Myślę, że wyjaśniłeś to w mojej głowie. To zabawne, jak byłem tak blisko kodu, że nawet nie mogłem myśleć. To był błąd w niektórych kodach produkcyjnych i intuicyjnie myślałem, że to źle, ale nie mogłem, aby moje życie zrozumiało dlaczego. – ScaryAardvark

+0

Tak, masz rację. Nasz kod produkcyjny ma go jako zmienny, a mój kod szybkiego testu nie. Poprawię moje pytanie odpowiednio :) – ScaryAardvark

+0

Jeszcze lepiej może być "volatile sig_atomic_t". –

Powiązane problemy