publicos - transient java
En un bloque sincronizado de Java, ¿las escrituras son visibles en todos los campos o solo en la variable sincronizada? (2)
Digamos que tienes este código:
private String cachedToken;
private final Object lockObject = new Object();
....
retrieveToken(){
synchronized(lockObject){
if (cachedToken == null){
cachedToken = goGetNewToken();
}
return cachedToken;
}
}
¿Será la escritura en cachedToken
visible para todos los hilos que se hayan bloqueado en lockObject
?
Por supuesto, synchronize
asegura dos cosas:
- Atomicidad
- Barrera de memoria (lo que espera en su caso) en todo el objeto
Mientras que, por ejemplo, los volatile
aseguran la barrera de la memoria pero no manejan la atomicidad.
Sí. La sincronización en lockObject establece que sucede antes de la relación (también configura una barrera de memoria). Esto significa que todos los hilos que posteriormente obtienen el bloqueo verán los cambios que ocurrieron mientras el bloqueo se mantenía previamente.
Sin embargo, por lo que vale, su implementación de inicialización diferida es defectuosa. Esta es la forma correcta:
private volatile String cachedToken;
retrieveToken() {
if (cachedToken == null) {
synchronized(lockObject) {
if (cachedToken == null) {
cachedToken = goGetNewToken();
}
}
}
return cachedToken
}
De esta forma, solo tiene que obtener el candado unas pocas veces cuando los hilos comienzan a solicitarlo. Después de eso, cachedToken no será nulo, y no necesitará sincronizar.