Pequeña pregunta sobre la visibilidad de la memoria.
Ejemplo de código1:
class CustomLock { private boolean locked = false; public boolean lock() { if(!locked) { locked = true; return true; } return false; } }Este código es propenso a errores en un entorno de subprocesos múltiples, primero debido al "si-entonces-actúa" que no es atómico, y segundo debido a posibles problemas de visibilidad de la memoria donde, por ejemplo, threadA establece el campo en verdadero, pero threadB que los deseos posteriores de leer el valor del campo podrían no verlo y aun así ver el valor falso.
La solución más simple es usar la palabra clave sincronizada, como en CodeSample2.
Ejemplo de código2:
class CustomLock { private boolean locked = false; public synchronized boolean lock() { if(!locked) { locked = true; return true; } return false; } }Ahora, ¿qué pasa si deseo usar una variable atómica y, para el ejemplo, un AtomicBoolean (la pregunta se aplica a todas las variables atómicas),
Ejemplo de código 3:
public static class CustomLock { private AtomicBoolean locked = new AtomicBoolean(false); public boolean lock() { return locked.compareAndSet(false, true); } }Dejando a un lado las consideraciones de mejor rendimiento, podemos ver que ahora hemos implementado una lógica similar a "if-then-act" de CodeSample1 , usando AtomicBoolean. Realmente no importa lo que el código haga lógicamente, la pregunta que tengo es si 2 subprocesos invocan el método lock() en CodeSample3 casi al mismo tiempo, mientras que está claro que cualquier operación de escritura en el campo ahora se realizará atómicamente. , ¿el uso de AtomicBoolean también garantiza la visibilidad de la memoria?
Perdón por la larga historia, solo quería asegurarme de ser lo más claro posible. Gracias chicos...
Sí, según los javadocs garantiza :
compareAndSet y todas las demás operaciones de lectura y actualización, como getAndIncrement, tienen los efectos de memoria de lectura y escritura de variables volátiles.
la pregunta que tengo es si 2 subprocesos invocan el método lock() en CodeSample3 casi al mismo tiempo, si bien está claro que cualquier operación de escritura en el campo ahora se realizará de forma atómica, ¿el uso de AtomicBoolean también garantiza la visibilidad de la memoria?
Para que AtomicBoolean maneje múltiples operaciones de diferentes subprocesos al mismo tiempo, debe garantizar la visibilidad de la memoria. Puede hacer la garantía porque envuelve un campo volatile . Es la semántica del lenguaje del volatile lo que garantiza que se crucen las barreras de la memoria para que múltiples subprocesos vean el valor más actualizado y que cualquier actualización se publique en la memoria principal.
Por cierto, su método de lock(...) debería estar listo para tryLock(...) porque es posible que no obtenga el bloqueo.