2011-12-06 17 views
5

Mam kilka kodu wielowątkowego (patrz pytanie Windows API Thread Pool simple example), dla których używam licznika do zidentyfikowania wątku.InterlockedIncrement vs EnterCriticalSection/counter ++/LeaveCriticalSection

Polecono mi użyć InterlockedIncrement do zwiększenia tego licznika w funkcji zwrotnej wątku. Jednak nie wydawało się to poprawnie zablokować zmiennej, ponieważ napotkałem pewne problemy z współbieżnością. Zastąpiłem InterlockedIncrement ręcznie za pomocą krytycznej sekcji: EnterCriticalSection/counter ++/LeaveCriticalSection i to teraz działa idealnie.

Dlaczego tak jest? Czy dwie opcje nie powinny być dokładnie równoważne? Pamiętaj, że mówię o uruchomieniu zaledwie kilku (około 10) wątków.

+0

W jaki sposób nie udało się poprawnie zablokować zmiennej? Jakie problemy z współbieżnością wystąpiły? – LukeH

+0

"InterlockedIncrement" i przyjaciele nie muszą blokować. Wykonuj pojedyncze instrukcje montażu. Czy możesz bardziej opisać problemy, które widziałeś? – Nate

+0

LukeH: licznik nie zawsze podawał ściśle rosnącą sekwencję liczb całkowitych. Czasami licznik, zaczynając od 0, robił: 0 1 2 2 4 5 ... – WhitAngl

Odpowiedz

26

Twój kod nie jest prawidłowo używany InterlockedIncrement.

InterlockedIncrement(&(thread.threadCount)); 
DWORD tid = (thread.threadCount-1)%thread.size(); 

Wykonuje przyrost atomową thread.threadCount, ale zamiast zapisywania atomowo-zwiększoną wartość, zignorować ją i wróć do thread.threadCount zmiennej (co może być zwiększany przez inny wątek w międzyczasie).

W twoim przypadku, dwa wątki zrobiły InterlockedIncrement prawie równocześnie, zwiększając je od 1 do 2, a następnie 2 do 3. Oba wątki następnie odczytały thread.threadCount i otrzymały 3 z powrotem (następnie odjęto 1, aby uzyskać końcowy wynik z 2).

Poprawny kod jest

LONG tidUnique = InterlockedIncrement(&(thread.threadCount)); 
DWORD tid = (tidUnique-1)%thread.size(); 

Unikalna wartość inkrementowany jest zwracany przez InterlockedIncrement. Musisz użyć tej wartości w swoich obliczeniach, jeśli chcesz zobaczyć unikalną wartość.