2011-12-06 7 views
5

Tengo un código multiproceso (vea la pregunta Windows API Thread Pool simple example) para el cual estoy usando un contador para identificar un hilo.InterlockedIncrement vs EnterCriticalSection/counter ++/LeaveCriticalSection

Se me ha recomendado usar un InterlockedIncrement para incrementar este contador en la función de devolución de llamada de la secuencia. Sin embargo, esto no pareció bloquear correctamente la variable, ya que encontré algunos problemas de simultaneidad. Reemplacé el InterlockedIncrement usando una sección crítica de forma manual: EnterCriticalSection/counter ++/LeaveCriticalSection y esto ahora funciona perfectamente.

¿Por qué es así? ¿No se supone que las dos opciones son estrictamente equivalentes? Tenga en cuenta que estoy hablando de lanzar solo un par (aproximadamente 10) de subprocesos.

+0

¿De qué manera no pareció bloquear correctamente la variable? ¿Qué problemas de concurrencia encontraste? – LukeH

+0

'InterlockedIncrement' y sus amigos no necesitan bloquear. Realice las instrucciones de montaje único. ¿Puedes ser más descriptivo sobre los problemas que estabas viendo? – Nate

+0

LukeH: el contador no siempre daba una secuencia consecutivamente estrictamente creciente de enteros. A veces, el contador, comenzando desde 0, estaba haciendo: 0 1 2 2 4 5 ... – WhitAngl

Respuesta

26

Su código no está utilizando InterlockedIncrement correctamente.

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

Esto realiza un incremento atómico de thread.threadCount, pero en lugar de guardar el valor incrementado atómicamente, que lo ignoran y volver a la variable thread.threadCount (que puede haber sido incrementado en otro hilo en el ínterin).

En su caso, lo que sucede es que dos hilos hicieron un InterlockedIncrement casi simultáneamente, incrementando desde 1 a 2, luego 2 a 3. Ambos hilos leen thread.threadCount y consiguieron volver 3 (continuación resta 1 para obtener un resultado final de 2).

el código correcto es

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

el valor incrementado único es devuelto por InterlockedIncrement. Debe usar ese valor en sus cálculos si desea ver el valor único.

Cuestiones relacionadas