La mia domanda riguarda pubblicazione sicura di valori di campo in Java (come rilevato qui Java multi-threading & Safe Publication).Pubblicazione sicura quando i valori vengono letti in metodi sincronizzati
quanto mi risulta, un campo può essere tranquillamente lettura (ovvero l'accesso da più thread vedrà il valore corretto) se:
- lettura e scrittura sono sincronizzati sullo stesso monitor
- campo è finale
- campo è volatile
Se la mia comprensione è corretta la seguente classe dovrebbe non essere thread-safe dal momento che il il valore iniziale è scritto senza queste caratteristiche. Tuttavia trovo difficile credere che sia necessario effettuare first
volatile
anche se si accede solo da un metodo synchronized
.
public class Foo {
private boolean needsGreeting = true;
public synchronized void greet() {
if (needsGreeting) {
System.out.println("hello");
needsGreeting = false;
}
}
}
Mi manca qualcosa? Il codice sopra è corretto e se sì perché? Oppure è necessario in questi casi rendere first
volatile
o utilizzare un final AtomicBoolean
o qualcosa di simile in aggiunta a per accedervi da un metodo synchronized
.
(Giusto per chiarire, mi rendo conto, che se il valore iniziale è stato scritto in un metodo synchronized
, sarebbe thread-safe, anche senza la parola chiave volatile
.)
"[...] che tipo di implica che non esiste un fronte prima -vista dalla fine di un costruttore di un oggetto all'inizio di un metodo arbitrario!". Questa "implicazione" non è corretta. – Grodriguez
Oh, certo, non è un'implicazione formale. Tuttavia, il fatto che affermino che la fine del costruttore si verifica prima dell'inizio del metodo di finalizzazione, dovremmo dire "suggerimenti su" che questo potrebbe non essere vero per i metodi arbitrari. – aioobe
@aioobe no, questo è solo per casi come il seguente codice: 'new SomeObject()', cioè chiamando il costruttore ma non memorizzando il riferimento. Quindi l'oggetto può essere immediatamente raccolto e il finalizzatore può essere immediatamente chiamato. La frase a cui ti riferisci si limita a fare in modo che il costruttore sia ancora finito prima dell'esecuzione del finalizzatore. –