2016-03-04 11 views
16

Capisco read-acquire (non riordina con successive operazioni di lettura/scrittura dopo di esso) e write-release (non riordina con operazioni di lettura/scrittura che lo precedono). mio q è: -Java volatile legge le scritture di svuotamento e fa letture di aggiornamento di scrittura volatile

  1. In caso di lettura acquisiscono, fare le scritture che lo precedono ottenere arrossato?
  2. In caso di write-release, le letture precedenti vengono aggiornate?

Inoltre, è in lettura-acquisizione come lettura volatile, e lo stesso rilascio di scrittura volatile in Java?

Perché questo è importante è che, prendiamo caso di scrittura-release ..

y = x; // a read.. let's say x is 1 at this point 
System.out.println(y);// 1 printed 
//or you can also consider System.out.println(x); 
write_release_barrier(); 
//somewhere here, some thread sets x = 2 
ready = true;// this is volatile 
System.out.println(y);// or maybe, println(x).. what will be printed? 

A questo punto, è x 2 o 1? Qui, considera pronto per essere volatile. Capisco che tutti i negozi prima di volatile saranno prima resi visibili .. e quindi solo il volatile sarà reso visibile. Grazie.

Ref: - http://preshing.com/20120913/acquire-and-release-semantics/

risposta

10

No: non tutte le scritture sono svuotate, né lo sono tutte le letture aggiornato.

Java funziona su una base "precedente" per il multithreading. Fondamentalmente, se A accade - prima di B, e B succede - prima di C, allora A succede - prima di C. Quindi la tua domanda equivale a se x=2 si verifica formalmente prima di qualche azione che legge x.

I fronti precedenti vengono fondamentalmente stabiliti mediante la sincronizzazione con le relazioni definite in JLS 17.4.4. Ci sono diversi modi per farlo, ma per volatili, è fondamentalmente ammonta a una scrittura di volatili happening-prima di una lettura a quello stesso volatile:

  • Una scrittura a una volatilità variabile V (§8.3 .1.4) sincronizza con tutte le letture successive di v da qualsiasi thread (dove "successivo" è definito in base all'ordine di sincronizzazione).

dato che, se il filo scrive ready = true, allora che scrivono da soli non significa niente accade-prima che (per quanto riguarda quella di scrittura è interessato). In realtà è il contrario; quello che scrive in ready accade prima delle cose su altri thread, se leggono ready.

Quindi, se l'altro thread (che imposta x = 2) aveva scritto al pronto dopo è impostato x = 2, e questa discussione (che hai postato sopra) poi leggere ready, allora vedrebbe x = 2. Questo perché la scrittura avviene prima della lettura e il thread di lettura vede quindi tutto ciò che il thread di scrittura ha fatto (fino alla scrittura inclusa).Altrimenti, hai una corsa di dati, e fondamentalmente tutte le scommesse sono disattivate.

Un paio di note aggiuntive:

  • Se non si dispone di un accade-prima di bordo, si può ancora vedere l'aggiornamento; è solo che non sei garantito. Quindi, non dare per scontato che se non leggi una scrittura su ready, vedrai ancora x = 1. Potresti visualizzare x = 1 o x = 2 o eventualmente qualche altra scrittura (fino al valore predefinito di x = 0)
  • Nel tuo esempio, sarà sempre 1, perché non lo fai rileggere x dopo il commento "da qualche parte qui". Ai fini di questa risposta, ho assunto che ci sia una seconda linea y=x immediatamente prima o dopo lo ready = true. Se non c'è, allora il valore di y sarà invariato rispetto a quello che era nel primo println, (supponendo che nessun altro thread lo modifichi direttamente - che è garantito se è una variabile locale), perché le azioni all'interno di un thread appaiono sempre come se fossero non riordinato
0

Per la vostra prima domanda, la risposta è che FIFO ordine

Per la vostra seconda domanda: pls controllare Volatile Vs Static in java

5

No, la lettura di una variabile volatile non svuoterà le scritture precedenti. Le azioni visibili garantiranno che le azioni precedenti siano visibili, ma la lettura di una variabile volatile non è visibile ad altri thread.

No, la scrittura su una variabile volatile non cancella la cache dei valori precedentemente letti. È garantito solo lo svuotamento delle scritture precedenti.

Nel tuo esempio, chiaramente sarà ancora 1 sull'ultima riga. È stato effettuato un solo incarico a e quello era 1, in base all'output precedente. Forse era un errore di battitura e intendevi scrivere println(x), ma anche in questo caso, il valore di 2 non è garantito per essere visibile.

7

Il modello di memoria Java non è specificato in termini di "lettura-acquisizione" e "scrittura-rilascio". Questi termini/concetti provengono da altri contesti e, dato che l'articolo che hai citato rende abbondantemente chiaro, sono spesso usati (da esperti diversi) per indicare cose diverse.

Se si vuole capire come funzionano i volatili in Java, è necessario comprendere il modello di memoria Java e la terminologia Java ... che è (fortunatamente) ben fondata e specificatamente specificata . Cercando di mappare il modello di memoria di Java su "read-acquisizione" e "write-release" semantica è una cattiva idea, perché:

  • "read-acquisizione" e "write-release" la terminologia e la semantica non sono ben specificato, e

  • un'ipotetica mappatura semantica JMM -> "lettura-acquisizione"/"scrittura-rilascio" è solo una possibile implementazione del JMM. Altre mappature possono esistere con semantica diversa e altrettanto valida.


1 - ... modulo che gli esperti hanno notato difetti in alcune versioni del JMM. Ma il punto è che è stato fatto un serio tentativo di fornire una specifica teoricamente valida ... come parte della specifica del linguaggio Java.