¿Cuándo es preferible usar boolean volátil en Java en lugar de AtomicBoolean?

He analizado las otras preguntas volátiles y Atomicxxxx en SO (incluida esta ) y he leído la descripción de java.util.current.atomic , y no estoy del todo satisfecho con los matices.

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

Supongamos que tengo

 volatile boolean flag; 

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

¿Hay un costo más alto para AtomicBoolean que el booleano volátil, en términos de

  • espacio de memoria
  • golpe de rendimiento ( volatile boolean parece requerir vallas de memoria, AtomicBoolean parece requerir vallas de memoria + algún locking menor en operaciones CAS según la descripción java.util.current.atomic)

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

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 va a hacerlo a menudo (como se attach en NIO).

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

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

Pero como todas las escrituras simultáneas son idempotentes y solo lee de un hilo, esto no debería ser un problema.

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, el intercalado puede verse así:

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

y esto podría estar bien (el segundo conjunto de flag en true no importa, ya que doStuff() aún presumiblemente verá lo que necesita el Tema 2.

Sin embargo, si revierte el orden, el hilo 3 lo hace:

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

entonces la actualización de Thread 2 podría perderse.

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

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

Hay mucha información buena aquí. 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.

Luego, uno o más hilos establecen el indicador (pero no lo borran). 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í, si no necesitas las habilidades especiales de AtomicBoolean, está perfectamente bien usar volatilidad para esto. De hecho, este es uno de los pocos usos razonables para la volatilidad.