10

Se accedo ad un oggetto all'interno di un metodo sincronizzato o di un blocco sincronizzato, anche tutti gli oggetti in quell'elemento a cui si accede sono sincronizzati?La sincronizzazione di Java aggiornerà la cache completa o solo l'oggetto su cui è stato sincronizzato?

Immaginate c'è un oggetto avente un metodo Queueadd() e take() sincronizzato, accettando e distribuendo l'oggetto complesso Thing. Thing contiene molte liste con altri oggetti diversi.

Ora la filettatura di immagine Before crea Thing e inserisce alcuni oggetti esistenti in Thing, modifica alcuni di questi oggetti e così via. Il thread Before aggiunge Thing a Queue. Un po 'più tardi thread After prende il Thing da Queue.

DOMANDA: Sarà Thing e tutti i suoi figli/subobject essere nello stesso stato di Before lasciato in? Anche se il thread After stava forse lavorando su uno di questi sottoelementi un po 'prima? Poiché io immagino che il processore per il thread After abbia ancora alcune informazioni memorizzate nella cache su tale sottoelemento (l'indirizzo di quel suboggetti è sempre lo stesso). Tutto questo materiale memorizzato nella cache sarebbe invalidato solo attraverso l'accesso all'oggetto padre Thing in modo sincronizzato?

Si prega di non dare risposte come utilizzare le librerie di concorrenza ecc. Voglio capire cosa sta succedendo.

risposta

7

Il concetto importante nel modello di memoria Java è happens-before order. I risultati delle azioni di scrittura che si verificano -prima delle azioni di lettura sono visibili per queste azioni di lettura. Altri risultati potrebbero o non essere visibili.

Il accadere, prima ordine indotta per ordine sincronizzazione delle azioni tra fili, e dal naturale ordine delle azioni dei singoli fili.

Se si è in Before sincronizzarsi su un oggetto (ad es.il vostro Queue), e fare tutte le manipolazioni di Thing ei suoi "oggetti secondari" dentro o prima di questo blocco sincronizzato e After sincronizzati sulla stessa Queue e legge questi oggetti nel o dopo il blocco sincronizzato, quindi tutti quei cambiamenti sono visibili a After.

9

Se un thread modifica una variabile, non è garantito un altro thread per visualizzare le modifiche tranne nei seguenti casi (beh, almeno nei seguenti casi: non sono sicuro al 100% se ce ne sono altri):

  • il thread di modifica lascia un blocco o un metodo sincronizzato; questo induce un flush della cache del thread (allo stesso modo un thread che entra in un blocco sincronizzato o un metodo induce un refresh) - questo è ciò che accade nel tuo caso
  • la variabile modificata è dichiarata volatile oppure è una delle variabili atomiche da java.util.concurrent.atomic
  • finiture filo modificante (questo induce anche un colore, anche l'inizio di un filo induce un aggiornamento)

Quindi se si sincronizza come spiegato, altri thread vedranno tutte le modifiche.

+1

sì lo so, ma non era proprio la mia domanda :-) La sincronizzazione deve anche influenzare le cache del processore, in modo che le modifiche vengano scaricate nella memoria comune, questo è ciò di cui si tratta la mia domanda. So che se si accede a un riferimento senza passare da un blocco sincronizzato a più thread paralleli, tutto diventa incasinato. Ma si tratta di passare più cose da un thread all'altro e assicurarsi che il datastrucuture sia ancora corretto. Capisci cosa intendo? –

+1

Vedere la risposta di Paulo. Il blocco dei thread è solo un aspetto della sincronizzazione, la relazione di happen-before (svuotamento della cache) è importante se non di più. È anche molto più complicato da comprendere e le API non sono chiare su quanto accade prima (ad esempio, penso che SwingUtilities.invokeLater provochi un successo prima, ma non ne sono sicuro al 100%). Consiglio vivamente la Concurrency Java in Practice di Goetz et al. Mettono molta enfasi su ciò che accade prima. – toto2

+0

Grazie per il downvoting senza spiegazione ... @Franz: Non mi era chiaro che stavi chiedendo del modello di memoria. Permettetemi di riconsiderare la mia risposta. – musiKk

Problemi correlati