multithreading - que - tags en español
¿Dónde está InterlockedRead? (3)
Win32 api tiene un conjunto de funciones InterlockedXXX para manipular de forma atómica y sincrónica variables simples, sin embargo, no parece haber ninguna función InterlockedRead, simplemente para recuperar el valor de la variable. ¿Cómo?
MSDN dice que:
Las lecturas simples y las escrituras en variables de 32 bits correctamente alineadas son operaciones atómicas
pero agrega:
Sin embargo, no se garantiza que el acceso esté sincronizado. Sin embargo, no se garantiza que el acceso esté sincronizado. Si dos subprocesos están leyendo y escribiendo desde la misma variable, no puede determinar si un subproceso realizará su operación de lectura antes de que el otro realice su operación de escritura.
Lo que significa, como lo entiendo, que una simple operación de lectura de una variable puede tener lugar mientras otra, por ejemplo, InterlockedAdd está en su lugar. Entonces, ¿por qué no hay una función enclavada para leer una variable?
Supongo que el valor se puede leer como el resultado InterlockedAdd-ing cero, pero no parece ser el camino correcto.
Creo que su interpretación de "no sincronizado" es incorrecta. Las lecturas simples son atómicas, pero usted mismo debe ocuparse de los problemas de reordenamiento y visibilidad de la memoria. El primero se maneja mediante el uso de instrucciones de cercado en los lugares apropiados, el segundo no es un problema con la lectura (pero una escritura concurrente potencial tiene que garantizar la visibilidad adecuada, lo que deberían hacer las funciones de entrelazado si se asignan a las instrucciones ASM BLOQUEADAS).
El quid de toda esta discusión es la alineación adecuada, que se define en la Partición I de xxx, en la sección '' 12.6.2 Alignment
'':
Built-in datatypes shall be properly aligned, which is defined as follows:
• 1-byte, 2-byte, and 4-byte data is properly aligned when it is stored at
a 1-byte, 2-byte, or 4-byte boundary, respectively.
• 8-byte data is properly aligned when it is stored on the same boundary
required by the underlying hardware for atomic access to a native int.
Básicamente, todos los valores de 32 bits tienen la alineación requerida, y en una plataforma de 64 bits, los valores de 64 bits también tienen la alineación requerida.
Sin embargo , tenga en cuenta que hay atributos para alterar explícitamente el diseño de las clases en la memoria, lo que puede hacer que pierda esta alineación. Sin embargo, estos son atributos específicos para este propósito, por lo que, a menos que se haya propuesto modificar el diseño, esto no debería aplicarse a usted.
Con eso fuera del camino, el propósito de la clase Interlocked
es proporcionar operaciones que (parafraseando) solo se puedan observar en su estado "antes" o "después". Las operaciones entrelazadas normalmente son solo una preocupación cuando se modifica la memoria (por lo general, en algún modo no trivial de tipo de intercambio de comparación). Como indica el artículo de MSDN que encontró, las operaciones de lectura (cuando están alineadas correctamente) pueden considerarse atómicas en todo momento sin más precauciones.
Sin embargo, hay otras consideraciones cuando se trata de operaciones de lectura:
- En las CPU modernas, aunque la lectura puede ser atómica, también puede devolver el valor incorrecto de un caché obsoleto en algún lugar ... aquí es donde es posible que deba hacer que el campo sea "volátil" para obtener el comportamiento que espera
- Si está tratando con un valor de 64 bits en un hardware de 32 bits, es posible que deba usar la operación
Interlocked.Read
para garantizar que todo el valor de 64 bits se lea en una sola operación atómica (de lo contrario, se puede realizar como 2 puntos separados). Lecturas de 32 bits que pueden ser de cualquier lado de una actualización de memoria) - El reordenamiento de sus lecturas / escrituras puede hacer que no obtenga el valor que esperaba; en cuyo caso puede ser necesaria alguna barrera de memoria (ya sea explícita o mediante el uso de las operaciones de clase
Interlocked
)
Breve resumen ; En lo que respecta a la atomicidad, es muy probable que lo que esté haciendo no necesite ninguna instrucción especial para la lectura ... sin embargo, es posible que tenga que tener cuidado con otras cosas, dependiendo de lo que esté haciendo exactamente.
La forma normal de implementar esto es usar una operación de intercambio de comparación (por ejemplo, InterlockedCompareExchange64
) donde ambos valores son los mismos. Tengo una sospecha de que esto se puede realizar de manera más eficiente que un agregado de 0 por alguna razón, pero no tengo pruebas que lo respalden.
Curiosamente, la clase Interlocked
de .NET no obtuvo un método de Read
hasta .NET 2.0. Creo que Interlocked.Read
se implementa utilizando Interlocked.CompareExchange
. (Tenga en cuenta que la documentación de Interlocked.Read
me parece un tanto engañosa: habla de atomicidad, pero no de volatilidad, lo que significa algo muy específico en .NET. No estoy seguro de lo que garantiza el modelo de memoria Win32 sobre la visibilidad de los valores recién escritos. de un hilo diferente, en todo caso.)