Palabra clave volátil en Java
La palabra clave volatile
en Java se utiliza para indicar que el valor de una variable será modificado por diferentes hilos. Garantiza que los cambios en una variable sean siempre visibles para otros hilos, evitando problemas de caché de hilos.
Utilización
La palabra clave volatile
se utiliza principalmente en la programación multihilo para garantizar que las actualizaciones de una variable se propaguen de forma predecible entre los hilos.
Syntax
volatile dataType variableName;
dataType
: El tipo de la variable (por ejemplo,int
,boolean
, etc.).variableName
: El nombre de la variable.
Ejemplos
Ejemplo 1: Uso básico
public class VolatileExample extends Thread {
private volatile boolean running = true;
public void run() {
while (running) {
// Thread is running
}
System.out.println("Thread stopped.");
}
public void stopRunning() {
running = false;
}
public static void main(String[] args) throws InterruptedException {
VolatileExample thread = new VolatileExample();
thread.start();
Thread.sleep(1000);
thread.stopRunning();
thread.join();
}
}
En este ejemplo, la variable running
está marcada como volatile
. El método run
comprueba la variable running
en un bucle. El método stopRunning
establece running
en false
, lo que detiene el bucle. La palabra clave volatile
garantiza que los cambios en running
sean visibles inmediatamente para el método run
.
Ejemplo 2: Volátil con varios hilos
public class VolatileCounter {
private volatile int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
public static void main(String[] args) throws InterruptedException {
VolatileCounter vc = new VolatileCounter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
vc.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter value: " + vc.getCounter());
}
}
En este ejemplo, la variable counter
está marcada como volatile
. Dos hilos incrementan la variable counter
simultáneamente. La palabra clave volatile
garantiza que cada hebra vea el valor más reciente de counter
.
Consejos y buenas prácticas
- Garantía de visibilidad: Utiliza
volatile
para garantizar la visibilidad de los cambios en las variables entre hilos. Garantiza que la lectura de una variable volátil siempre devuelva la escritura más reciente de cualquier hilo. - Atomicidad:
volatile
no garantiza la atomicidad. Para acciones compuestas (por ejemplo, operaciones de incremento), considera la posibilidad de utilizar otros mecanismos de sincronización como los bloquessynchronized
oAtomicInteger
.private AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet();
- Casos prácticos: Apropiado para banderas, variables de estado y otras variables en las que el último valor es crítico pero no se requieren operaciones compuestas.
- Evita el uso excesivo: El uso excesivo de
volatile
puede provocar problemas de rendimiento. Utilízalo sólo cuando sea necesario para garantizar la visibilidad. - Combinar con otra sincronización: En escenarios complejos, combina
volatile
con otros mecanismos de sincronización para garantizar tanto la visibilidad como la atomicidad.private volatile boolean flag = false; synchronized (this) { flag = true; }
- Consistencia de la memoria: La palabra clave
volatile
ayuda a evitar errores de consistencia de memoria estableciendo una relación "sucede antes", asegurando que los cambios en una variable volátil sean visibles para otros subprocesos.