multithreading - threads - thread library c++
¿Cuándo debería utilizarse la función Winlock InterlockedExchange? (7)
Encontré la función InterlockedExchange y me preguntaba cuándo debería usar esta función. En mi opinión, establecer un valor de 32 Bit en un procesador x86 siempre debe ser atómico.
En el caso en que quiera usar la función, el nuevo valor no depende del valor anterior (no es una operación de incremento). ¿Podría darnos un ejemplo donde este método es obligatorio (no estoy buscando InterlockedCompareExchange)
En una máquina multiprocesador o multinúcleo, cada núcleo tiene su propio caché, por lo que cada núcleo tiene cada una de ellas una "vista" potencialmente diferente de lo que es el contenido de la memoria del sistema.
Los mecanismos de sincronización de subprocesos se encargan de sincronizar los núcleos. Para obtener más información, consulte http://blogs.msdn.com/oldnewthing/archive/2008/10/03/8969397.aspx o google para obtener y liberar semántica
Escribir un valor nunca es atómico por defecto. Cuando escribe un valor en una variable, se generan varias instrucciones de la máquina. Con sistemas operativos modernos y preventivos, el sistema operativo podría cambiar a otro hilo entre las operaciones individuales de la escritura.
Esto es aún más un problema en las máquinas multiprocesador, donde varios subprocesos podrían estar ejecutándose al mismo tiempo y tratando de escribir en una sola ubicación de memoria simultáneamente.
Las operaciones interconectadas evitan esto al usar instrucciones especializadas para hacer la escritura (x86 tiene instrucciones dedicadas para este tipo de situación), que hacen la lectura-modificación-escritura en una instrucción. Estas instrucciones también bloquean el bus de memoria de todos los procesadores, para garantizar que ningún otro hilo de ejecución pueda escribir en el valor al mismo tiempo.
Establecer un valor de 32 bits es atómico, pero solo si está configurando un literal.
b = a son 2 operaciones:
mov eax,dword ptr [a]
mov dword ptr [b],eax
Teóricamente podría haber alguna interrupción entre la primera y la segunda operación.
InterlockedExchange
es a la vez una escritura y una lectura, devuelve el valor anterior.
Esto es necesario para garantizar que otro subproceso no escriba un valor diferente justo después de que lo hizo. Por ejemplo, supongamos que estás tratando de incrementar una variable. Puede leer el valor, agregar 1, luego establecer el nuevo valor con InterlockedExchange
. El valor devuelto por InterlockedExchange
debe coincidir con el valor que leyó originalmente, de lo contrario, probablemente otro subproceso lo incremente al mismo tiempo, y deberá dar la vuelta e intentar nuevamente.
Además de escribir el nuevo valor, InterlockedExchange
también lee y devuelve el valor anterior; toda esta operación es atómica. Esto es útil para algoritmos sin bloqueo .
(Por cierto, no se garantiza que las escrituras de 32 bits sean atómicas. Considere el caso en que la escritura no está alineada y se extiende a ambos lados de un límite de caché, por ejemplo).
InterlockedExchange se asegura de que el cambio de una variable y el retorno de su valor original no sean interrumpidos por otros hilos.
Entonces, si ''i'' es un int, estas llamadas (tomadas individualmente) no necesitan InterlockedExchange alrededor de ''i'':
a = i;
i = 9;
i = a;
i = a + 9;
a = i + 9;
if(0 == i)
Ninguna de estas afirmaciones se basa tanto en los valores iniciales Y finales de ''i''. Pero estas siguientes llamadas sí necesitan InterlockedExchange alrededor de ''i'':
a = i++; //a = InterlockedExchange(&i, i + 1);
Sin él, dos subprocesos que se ejecutan a través de este mismo código pueden obtener el mismo valor de ''i'' asignado a ''a'' o ''a'' pueden omitir inesperadamente dos o más números.
if(0 == i++) //if(0 == InterlockedExchange(&i, i + 1))
Dos hilos pueden ejecutar el código que solo se supone que debe ocurrir una vez.
etc.
wow, tantas respuestas conflictivas. Es difícil discernir quién tiene la razón, quién está equivocado y qué información es engañosa.
No estoy seguro de la respuesta también, dadas las medias respuestas anteriores, pero creo que funciona así, puedo estar equivocado, y será interesante averiguar si estoy:
- Las lecturas y escrituras de 32 bits SON atómicas, pero dependiendo de su código, eso puede no significar mucho.
- no se preocupe por lecturas / escrituras no alineadas. TODAS las escrituras de 32 bits en una variable de 32 bits tienen que estar alineadas o las fallas de página de la máquina.
- no se preocupe por un ajuste de escritura al final de una página almacenada en caché, eso no puede suceder.
- Si necesita escribir-luego-leer en un hilo, y está escribiendo en otro hilo, entonces necesita usar InterlockedExchange. Si simplemente lees el valor en un hilo y lo escribes en otro, entonces no necesitas usarlo, pero esos valores pueden ser contundentes debido al multihilo.