dire che ho un oggetto di dati:pool di thread, dati condivisi, Java Sincronizzazione
class ValueRef { double value; }
Dove ogni oggetto dati vengono memorizzati in una collezione maestro:
Collection<ValueRef> masterList = ...;
anche io disporre di una raccolta di lavori, in cui ogni lavoro ha una raccolta locale di oggetti dati (in cui ogni oggetto dati viene visualizzato anche nello masterList
):
class Job implements Runnable {
Collection<ValueRef> neededValues = ...;
void run() {
double sum = 0;
for (ValueRef x: neededValues) sum += x;
System.out.println(sum);
}
}
caso d'uso:
for (ValueRef x: masterList) { x.value = Math.random(); }
Compilare una coda di lavoro con alcuni posti di lavoro.
sveglia un pool di thread
Attendere ciascun lavoro è stato valutato
Nota: Durante la valutazione del lavoro, tutti i valori sono tutti costanti. Tuttavia, i thread hanno probabilmente valutato i lavori nel passato e conservano i valori memorizzati nella cache.
Domanda: qual è la quantità minima di sincronizzazione necessaria per garantire che ogni thread visualizzi gli ultimi valori?
Capisco sincronizzare dal monitor/lock-perspective, non capisco la sincronizzazione dalla cache/flush-prospettiva (cioè ciò che è garantito dal modello di memoria in entrata/uscita del blocco sincronizzato).
Per me, mi sembra di dover sincronizzare una volta nella thread che aggiorna i valori per eseguire il commit dei nuovi valori nella memoria principale e una volta per thread di lavoro, per svuotare la cache in modo da leggere i nuovi valori. Ma non sono sicuro di come sia meglio farlo.
Il mio approccio: creare un monitoraggio globale: static Object guard = new Object();
Quindi, sincronizzare il guard
, durante l'aggiornamento della lista principale. Quindi, infine, prima di avviare il pool di thread, una volta per ogni thread nel pool, sincronizzare su guard
in un blocco vuoto.
Ciò causa realmente un flusso completo di qualsiasi valore letto da quel thread? O solo i valori toccati all'interno del blocco di sincronizzazione? In questo caso, invece di un blocco vuoto, forse dovrei leggere ogni valore una volta in un ciclo?
Grazie per il vostro tempo.
Edit: Credo che la mia domanda si riduce a, una volta che esce da un blocco sincronizzato, non ogni prima lettura (dopo quel punto) vai a memoria principale? Indipendentemente da ciò su cui sono sincronizzato?
Sembra quasi un luogo perfetto per sfruttare la parola chiave volatile – ControlAltDel
Sto scrivendo una volta (in modo efficace-costante), ma potenzialmente leggendo milioni di volte. Volatile non viene mai memorizzato nella cache locale. Se avessi creato il pool di thread ogni volta, il codice funzionerebbe perfettamente senza la sincronizzazione/volatile (poiché non esisterebbe alcuna cache precedente). –
Qui non vedo un bisogno di volatile. Se ValueRef è effettivamente immutabile, rendilo semplicemente immutabile. Usa doppio. Crea una nuova collezione per ogni lavoro prima che sia pianificato e includilo in unmodifiableCollection (solo come promemoria). Quale problema prevedi? –