2008-10-16 10 views
19

Me encontré con 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 deseo usar la función, el nuevo valor no depende del valor anterior (no es una operación de incremento). Podría dar un ejemplo en este método es obligatorio (no estoy en busca de InterlockedCompareExchange)¿Cuándo debería utilizarse la función Winlock InterlockedExchange?

Respuesta

4

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.

mecanismos de sincronización de rosca se encargan de la sincronización entre los núcleos, para más información ver http://blogs.msdn.com/oldnewthing/archive/2008/10/03/8969397.aspx o Google para adquirir y liberar la semántica

+2

Los cachés son secundarios aquí. Incluso si no hay cachés y las CPU hablaban con la memoria, la secuencia de lectura/escritura normal no es atómica. – Suma

10

InterlockedExchange es tanto 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á volver a intentarlo y volver a intentarlo.

+3

En este caso, yo usaría InterlockedCompareExchange, porque el control de si el valor todavía era el original ya está hecho por el método. – EFrank

+3

O simplemente InterlockedIncrement –

11

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 lock-free algorithms.

(Por cierto, las escrituras de 32 bits son no garantiza que sea atómica. Consideremos el caso en que la escritura es no alineada y extiende a ambos lados de un límite de caché, por ejemplo.)

+0

Sería atómico desde el punto de vista del software que se ejecuta en el procesador, pero no desde el punto de vista del hardware que se encuentra en el bus. –

+1

¿Sería atómico desde el punto de vista del software que se ejecuta en otro núcleo? ¿Qué pasa con una escritura que se extiende a lo largo de un límite de página y desencadena una falla? Han pasado años desde que hice alguna codificación x86 de bajo nivel, supongo que puedo estar mintiendo:/ – moonshadow

3

establecer un valor de 32 bits es atómico, pero solo si estás estableciendo un literal.

b = a es de 2 operaciones:

mov   eax,dword ptr [a] 
mov   dword ptr [b],eax 

Teóricamente podría haber algunos interrupción entre la primera y segunda operación.

+4

Y si hubiera alguna interrupción, ¿qué? Tomará un poco más de tiempo, pero el valor en eax no cambiará. El verdadero objetivo de InterlockedExchange es que es de lectura y escritura atómica. – Suma

+1

¿Entonces qué? Infierno. La interrupción puede causar una llamada al sistema, el sistema llama a un interruptor de contexto y luego otro hilo cambia el valor. Entonces EAX se restaura y el valor se cambia de nuevo. Las condiciones de carrera son especialmente fatales cuando se cuentan las referencias. Algunos subprocesos pueden incrementar el valor mientras que otro subproceso disminuye el valor, o dos subprocesos pueden incrementarlo al mismo tiempo. Que EAX se restaure no es la solución, es el problema. –

+0

Y empeora cuando hay más de una CPU/núcleo. – SamB

3

Escribir un valor nunca es atómica 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 incluso 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 de enclavamiento evitan esto mediante el uso de instrucciones especializadas para realizar la escritura (x86 tiene instrucciones específicas para este tipo de situaciones), 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.

+0

-1, las escrituras alineadas incorrectas son atómicas en x86. – Johan

2

InterlockedExchange se asegura de que el cambio de una variable y el retorno de su valor original no sean interrumpidos por otros hilos.

lo tanto, si 'i' es un int, estas llamadas (tomados individualmente) no necesitan InterlockedExchange torno a 'i':

a = i; 
i = 9; 
i = a; 
i = a + 9; 
a = i + 9; 
if(0 == i) 

Ninguna de estas declaraciones invocar a la vez los valores inicial y final del ' yo'. Pero estas llamadas siguientes sí es necesario InterlockedExchange torno a 'i':

a = i++; //a = InterlockedExchange(&i, i + 1); 

Sin ella, dos subprocesos que se ejecutan a través de este mismo código podría obtener el mismo valor de 'i' asignado a 'a' o 'a' puede saltar inesperadamente dos o más números

if(0 == i++) //if(0 == InterlockedExchange(&i, i + 1)) 

Dos subprocesos pueden ejecutar el código que solo se supone que debe ocurrir una vez.
etc.

+0

Ejemplo incorrecto 'a = InterlockedExchange (& i, i + 1);'.Su 'i' podría ser cambiado por la otra CPU entre' i + 1' y 'InterlockedExchange'. – Fr0sT

-1

guau, muchas respuestas contradictorias. Es difícil discernir quién tiene la razón, quién está equivocado y qué información es engañosa.

estoy seguro de la respuesta también, dadas las anteriores respuestas a medias, pero creo que funciona de esta manera, puedo estar equivocado, y será interesante averiguar si soy:

  1. lectura de 32 bits & escribe ARE atomic, pero dependiendo de su código, eso puede no significar mucho.
  2. 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.
  3. no se preocupe por un ajuste de escritura al final de una página en caché, eso no puede suceder.
  4. Si necesita escribir y 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.
+0

-1 Los valores de 32 bits no necesitan alinearse en x86. Y las escrituras de 32 bits son atómicas en x86, pero no en muchas otras arquitecturas. – Johan

Cuestiones relacionadas