2011-06-18 12 views
27

He estado leyendo de muchas fuentes que the volatile keywordis not helpfulin multithreaded scenarios. Sin embargo, esta afirmación se ve desafiada constantemente por las funciones de operación atómica que aceptan punteros volatile.Si la volatilidad es inútil para enhebrar, ¿por qué las operaciones atómicas requieren punteros a los datos volátiles?

Por ejemplo, en Mac OS X, que tienen la familia OSAtomic función:

SInt32 OSIncrementAtomic(volatile SInt32 *address); 
SInt32 OSDrecrementAtomic(volatile SInt32 *address); 
SInt32 OSAddAtomic(SInt32 amount, volatile SInt32 *address); 
// ... 

y parece que hay un uso similar de la volatile palabra clave en Windows para Interlocked operaciones:

LONG __cdecl InterlockedIncrement(__inout LONG volatile *Addend); 
LONG __cdecl InterlockedDecrement(__inout LONG volatile *Addend); 

También parece que en C++ 11, los tipos atómicos tienen métodos con el modificador volatile, lo que de alguna manera debe significar que la palabra clave volatile tiene algún tipo de relación con atomicit y

Entonces, ¿qué es lo que me falta? ¿Por qué los vendedores de SO y los diseñadores de bibliotecas estándar insisten en usar la palabra clave volatile para enhebrar si no es útil?

+3

No es tan volátil no tiene ningún uso, es más que datos volátiles no garantiza las operaciones atómicas –

+3

No es una víctima, pero se superpone con http://stackoverflow.com/questions/2479067/why-is-the-volatile- qualifier-used-through-out-stdatomic –

Respuesta

17

De repente me vino a la mente que simplemente malinterpreté el significado de volatile*. Al igual que const* significa que la punta no debe cambiar, volatile* significa que la punta no se debe almacenar en caché en un registro. Esta es una restricción adicional que se puede agregar libremente: tanto como puede lanzar char* a const char*, puede convertir int* en volatile int*.

Aplicando el modificador volatile a las puntas simplemente asegura que las funciones atómicas se pueden usar en variables ya volatile. Para variables no volátiles, agregar el calificador es gratis. Mi error fue interpretar la presencia de la palabra clave en los prototipos como un incentivo para usarla en lugar de como una conveniencia para quienes la usan.

+0

También hace 'volátil' útil para evitar que accidentalmente pase una variable compartida por referencia a una función que no reconoce hilos. –

1

Bueno, la palabra clave 'volátil' se asegura de que el compilador siempre cargue/almacene el valor de una variable de/a la memoria cada vez que la variable aparezca en su código.
Esto evita ciertas optimizaciones, p. que el valor simplemente se carga en un registro una vez y luego se usa varias veces.
Es útil cuando tiene múltiples hilos que pueden modificar variables 'compartidas' entre los hilos. Deberá asegurarse de cargar/almacenar siempre el valor desde/hacia la memoria para verificar su valor que puede haber sido modificado por otro hilo. Si no se utilizó el volátil, el otro subproceso podría no haber escrito el nuevo valor en la memoria (pero ponerlo en un registro u otro tipo de optimización podría haber tenido lugar) y el primer subproceso no notaría ningún cambio de valor.

En la dirección SInt32 * volátil de su caso, le dice al compilador que la memoria apuntada por dirección está sujeta a cambios por cualquier fuente. De ahí la necesidad de una operación atómica.

+0

Su respuesta también entra en contradicción casi directa con la [publicación del blog de Arch Robinson] (http://software.intel.com/en-us/blogs/2007/11/30/ volátil-casi-inútil-para-multi-threaded-programming /), arquitecto de Threading Building Blocks en Intel, al que he vinculado en mi pregunta. – zneak

+0

@zneak En realidad no. Nunca mencioné que se evitaría el "reordenamiento del código". Simplemente tiene que indicar que 'SInt32 * dirección' con 'volátil' ya que puede estar sujeto a cambios por cualquier impacto externo. Las operaciones atómicas necesitan lidiar con esto para mantener la atomicidad. Por lo tanto, volátil es la forma correcta de marcar este comportamiento. – iolo

22

volátil No es inútil para el acceso compartido por múltiples hilos - es sólo que no es necesariamente suficiente:

  • que no necesariamente proporciona la semántica de barrera de memoria que podrían ser necesarias;
  • no ofrece garantías de acceso atómica (por ejemplo, si el objeto volátil es más grande que la nativa tamaño de la palabra de memoria de la plataforma)

Además, también se debe tener en cuenta que el volatile calificador en los argumentos de puntero a las API de su ejemplo solo realmente realmente agregan la capacidad para que las API reciban punteros a objetos volatile sin quejarse, no requiere que los punteros apunten a objetos reales volatile. El estándar permite que un puntero no calificado se convierta automáticamente en un puntero calificado. Automáticamente yendo por el otro camino (puntero calificado a no calificado) no está previsto en el estándar (los compiladores generalmente lo permiten, pero emiten una advertencia).

Por ejemplo, si se InterlockedIncrement() prototipo como:

LONG __cdecl InterlockedIncrement(__inout LONG *Addend); // not `volatile*` 

La API todavía podrían implementarse para que funcione correctamente internamente. Sin embargo, si el usuario tenía un obeject volátil que quería pasar a la API, se requeriría un molde para evitar que el compilador emitiera una advertencia.

Desde (necesario o no), estas API se utilizan a menudo con volatile objetos calificados, añadiendo el calificador volatile al argumento puntero impide el diagnóstico inútiles que se genere cuando se utiliza la API, y perjudica nada cuando la API se utiliza con un puntero a un objeto no volátil.

+0

¿Has leído mi respuesta y has editado la tuya para que coincida? ;) – zneak

+0

@zneak: solo una coincidencia: todavía no he leído las otras respuestas. –

+1

+1 para el "necesario pero no suficiente" – jcoder

2

C++ 11 tiene atómica para ambas variables y no volatilevolatile.

Si los intrínsecos del compilador toman un puntero a volatile int, eso significa que puede usarlo incluso si la variable es volátil. No le impide usar la función en datos que no sean volatile.

Cuestiones relacionadas