2011-02-02 13 views
47

He visto las otras preguntas volátiles vs. Atomicxxxx en SO (incluyendo this one) y he leído the description of java.util.current.atomic, y no estoy del todo satisfecho con los matices.¿Cuándo es preferible usar booleano volátil en Java en lugar de AtomicBoolean?

Si estoy tratando de decidir entre usar volatile boolean y AtomicBoolean, ¿existen diferencias prácticas además de las operaciones atómicas de lectura, escritura y modificación que ofrece AtomicBoolean? (Por ejemplo compareAndSet() y getAndSet())

Supongamos que tengo

volatile boolean flag; 

Entonces uno o más hilos fijan la bandera (pero no está claro él). Si tengo un hilo que lee el indicador, y si se establece, realiza una acción, y luego borra el indicador, ¿es adecuado el volatile?

¿Hay un costo mayor a AtomicBoolean de booleano volátil, en términos de

  • espacio de memoria
  • impacto en el rendimiento (volatile boolean parece requerir la esgrima memoria, AtomicBoolean parece requerir cercas de memoria + algunos menores de bloqueo en Operaciones CAS según la descripción java.util.current.atomic)

Mi intuición es simplemente ir con AtomicBoolean y estar a salvo, pero quiero entender si alguna vez hay una situación para usar volatile boolean en su lugar (p. si tuviera miles de instancias de ellos y el rendimiento fuera un problema).

+1

¿Qué estás tratando de hacer con esta bandera? ¿Estás usando la bandera para controlar la concurrencia o alguna otra cosa? Me pregunto si el problema subyacente ayudaría a explicar qué respuesta estás buscando. –

+1

'Si tengo un hilo que lee el indicador, y si se establece, realiza una acción, y luego borra el indicador, ¿es adecuado volátil?' Sí, eso es exactamente lo que se supone que la palabra clave 'volátil' debe resolver por usted. –

+0

@Jonathan: era solo un ejemplo en particular ... Estaba pensando en un programa donde tengo componentes marcados como "sucios" que necesitan persistencia. Los componentes se marcan como "sucios" y un administrador de persistencia encuentra los componentes sucios, guarda su estado y los marca como no sucios. –

Respuesta

15

Esencialmente todo AtomicBoolean es un volatile boolean en un objeto.

Habrá una pequeña sobrecarga por objeto. Probablemente insignificante, pero posiblemente más memoria para entrar en el caché.

Si necesita usar AtomicBooleanFieldUpdater, entonces hay una gran cantidad de sobrecarga de rendimiento.Puede estar bien si no lo va a hacer a menudo (como attach en NIO).

+3

En realidad es un http 'volátil int' : //www.docjar.com/html/api/java/util/concurrent/atomic/AtomicBoolean.java.html – helpermethod

+1

@Helper Método No creo que importe. Enteramente hasta la implementación de lo que hace. –

+0

internamente, java ama los enteros, más que cualquier otro tipo primitivo. – bvdb

2

Luego uno o más hilos establecen el indicador (pero no lo borran). Si tengo un hilo que lee el indicador, y si establece, realiza una acción, y luego borra el indicador, ¿es adecuado volátil?

Sí, si no necesita las habilidades especiales de AtomicBoolean, está perfectamente bien usar volátiles para esto. De hecho, este es uno de los pocos usos razonables para la volatilidad.

62

La principal diferencia entre AtomicBoolean y volatile desde un punto de vista práctico es que el-y-set operación de comparación no es atómica con volatile variables.

volatile boolean b; 

void foo() { 
    if(b) { 
    //Here another thread might have already changed the value of b to false 
    b = false; 
    } 
} 

Pero ya que todas sus escrituras concurrentes es idempotente y sólo se lee de un hilo, esto no debería ser un problema.

+8

+1 para mostrar el concepto idempotente –

+0

No existe una operación de comparación y ajuste en el lenguaje para 'volátiles', por lo que no puede ser antieconómico. Las operaciones de comparación y ajuste suministradas por la biblioteca ('AtomicBooleanFieldUpdate' y sus amigos) son atómicas. –

+2

@Tom Hawtin - tackline Compare-and-set (o swap) es, sin embargo, una operación en general, a pesar de que no hay una implementación incorporada en Java excepto las clases 'Atomic *'. http://en.wikipedia.org/wiki/Compare-and-set – biziclop

18

No estoy seguro de estar completamente de acuerdo con las otras respuestas aquí; La respuesta de biziclop es correcta hasta donde llega, pero no estoy seguro de que podamos concluir que estás a salvo a menos que sepamos más detalles.

En el caso simple, la intercalación podría tener este aspecto:

Thread 1 (writer) Thread 2 (Writer) Thread 3 (Reader) 
----------------- ----------------- ----------------- 
flag = true; 
             if (flag) { 
        flag = true; 
             flag = false; 
             doStuff(); 

y esto puede ser muy bien (el segundo conjunto de flag a true no importa, como se doStuff() presumiblemente aún ver cualquier Tema 2 necesidades . haciendo

Sin embargo, si se invierte el orden de hilo 3 hace:

Thread 1 (writer) Thread 2 (Writer) Thread 3 (Reader) 
----------------- ----------------- ----------------- 
flag = true; 
             if (flag) { 
             doStuff(); 
        flag = true; 
             flag = false; 

continuación Thre La actualización del anuncio 2 podría perderse.

Por supuesto, debe tener el mismo cuidado con lo que hace el Subproceso 2, para asegurarse de que sea visible en el Subproceso 3. Si hay otro estado que el Subproceso 2 necesita establecer, el orden también es importante allí.

En el caso simple, sí, está bien, pero si se vuelve más complejo que el simple parpadeo de las banderas, entonces es mucho más difícil razonar.

+7

Buen punto. Aunque vale la pena mencionar que en el segundo caso AtomicBoolean tampoco ayudará. La sincronización en toda regla es necesaria entonces. –

+3

@Cowen: nunca he visto el entrelazado visualizado como tal, pero está muy claro. Lo hago mentalmente cuando leo código enhebrado, pero esta es una buena técnica para documentar casos cuando se explican las condiciones/debilidades de la raza en el código enhebrado. – kevinarpe

+0

@SergeyTachenov ¿No resolverá AtomicBoolean.getAndSet() en el subproceso 3 este problema? –

6

Aquí hay mucha información útil. Sin embargo, agregaría otra diferencia que puede ser útil. Puede tener una matriz de AtomicBooleans pero no puede (que yo sepa) tener una matriz de booleanos volátiles.

+0

No, pero aún puede tener un SynchronizedSet u otro conjunto sincronizado de booleanos, que publican de manera segura la matriz – pkran

Cuestiones relacionadas