2016-04-06 11 views
5

Poiché StringBuffer è thread-safe, può essere tranquillamente pubblicato. Si consideri il costruttore pubblico di StringBuffer (sources):Come pubblicare StringBuffer in modo sicuro?

public StringBuffer() { 
    super(16); 
} 

dove super(16) designa questo:

AbstractStringBuilder(int capacity) { 
    value = new char[capacity]; 
} 

dove il valore dichiarato come

char[] value; 

DOMANDA: Come pubblicare StringBuffer in sicurezza?

Ho la seguente classe:

public class Holder{ 
    public final StringBuffer sb = new StringBuffer(); 
} 

può essere considerato come sicuro-pubblicazione? Penso, non può.

final garantisce che vedremo un nuovo valore del riferimento sb. Tuttavia, la scrittura nello stato interno di sb all'interno di AbstractStringBuilder(int capacity) non è sincronizzata. Quindi non c'è l'ordine happens-before che a sua volta significa che leggere da value si verifica quando si invoca sb.append(2); e si scrive in value nel costruttore sono racy.

Potete aiutarmi a capire questo? Forse ho perso qualcosa ...

+0

Intende per 'sb' essere una variabile di istanza o dovrebbe essere statica? – Paolo

+0

Se si desidera un provider thread-safe di un testo/stringa che cambia a volte, quindi utilizzare ['AtomicReference '] (https://docs.oracle.com/javase/8/docs/api/java/util/ concurrent/atomico/AtomicReference.html). StringBuffer è per l'aggiunta simultanea ad esso, un caso d'uso raro. –

+0

@Paolo No, è esattamente un'istanza varialbe. L'inizializzazione statica si è verificata durante l'inizializzazione di una classe che comporta il blocco inter-JVM, che inturns garantisce la coerenza della memoria. –

risposta

4

Potete aiutarmi a capire questo? Forse ho perso qualcosa ...

AFAIR dopo JSR-133 è garantito che final campo della classe che viene inizializzato come nel tuo esempio è esente da race condition durante il processo di creazione di un'istanza e solo il valore corretto sarà esposto dopo init

UPD: via Brian Goetz

Secondo il nuovo modello di memoria, v'è qualcosa di simile ad un accade-prima relazione tra la scrittura di un campo finale in ac onstructor e il caricamento iniziale di un riferimento condiviso a quell'oggetto in un altro thread. Quando il costruttore termina, tutte le scritture sui campi finali (e sulle variabili raggiungibili indirettamente attraverso quei campi finali) diventano "congelate" e qualsiasi thread che ottiene un riferimento a quell'oggetto dopo il freeze è garantito per vedere i valori congelati per tutti campi congelati. Scrive che l'inizializzazione dei campi finali non verrà riordinata con le operazioni successive al blocco associato al costruttore.

IMHO la tua domanda (e la comprensione della concorrenza) è molto buona perché non è una caratteristica di progettazione del linguaggio/piattaforma evidente ed è stato risolto solo in Java SE 5.0

+0

Valore corretto del riferimento, sì. Ma per quanto riguarda lo stato dell'oggetto a cui ci si rifrange? –

+0

Sì, gli ultimi aggiornamenti spiegano tutto. Grazie. –

+0

Quindi, senza un modificatore finale non sarebbe considerato una pubblicazione sicura. Destra? –

2

consultare Javadoc per StringBuffer.

I buffer di stringa sono sicuri per l'utilizzo da più thread. I metodi sono sincronizzati ove necessario in modo che tutte le operazioni su una particolare istanza si comportino come se si verifichino in qualche ordine seriale coerente con l'ordine delle chiamate di metodo effettuate da ciascuno dei singoli thread coinvolti.

Questo dovrebbe essere una garanzia sufficiente.

2

La creazione della variabile di istanza di sb è thread-safe poiché viene eseguita contemporaneamente alla creazione di un'istanza di Holder.

Il motivo è thread-safe è che è una variabile di istanza e non c'è modo filo 1 può iniziare a costruire un'istanza di Holder (e in associazione un nuovo StringBuffer) e poi per un secondo filo di saltare e iniziare a correre tramite il costruttore per la stessa istanza.

cioè se il codice ha due thread che sia venuto attraverso le linee

Holder h = new Holder(); 

Faresti finisce con due istanze separate di Titolare e poi una gara per la quale è assegnato a h, che è un problema diverso

Problemi correlati