2013-04-28 13 views
6

sto leggendo il libro codice Crack Intervista di recente, ma c'è un paragrafo confondermi un sacco a pagina 257:visibilità Discussione tra un processo

Un thread è un particolare percorso di esecuzione di un processo; quando un thread modifica una risorsa di processo, la modifica è immediatamente visibile ai thread di pari livello.

IIRC, se un thread apportare una modifica a una variabile, la modifica viene dapprima salva nella cache CPU (per esempio, cache L1), e non garantisce la sincronizzazione ad altri thread meno che la variabile viene dichiarata come volatile .

Ho ragione?

+3

Se si parla di volatile, è necessario specificare anche la lingua. In C e C++, volatile è generalmente inutile per la sincronizzazione dei thread, mentre in Java è utile. –

+0

@doomster, grazie ma credo che 'volatile' abbia lo stesso ruolo in Java e in C++, potresti spiegare perché è diverso dalla tua parte? – MrROY

+3

Sono simili nell'intento, ma non equivalenti. In Java, hai garanzie molto specifiche riguardo il loro comportamento nei programmi multithread. Per C++, vedere http://stackoverflow.com/q/2484980/1968182. –

risposta

8

No, ti sbagli. Ma questo è un equivoco comune a.

Ogni moderna CPU multi-core ha hardware cache coherence. La L1 e le cache simili sono invisibili. Le cache della CPU come la cache L1 hanno niente da fare con visibilità della memoria.

Le modifiche sono visibili immediatamente quando un thread modifica una risorsa di processo. Il problema sono le ottimizzazioni che fanno sì che le risorse del processo non vengano modificate esattamente nell'ordine specificato dal codice.

Se il codice ha k = j; i = 4; if (j == 2) foo(); un ottimizzatore potrebbe vedere che il primo compito legge il valore di j. Quindi potrebbe non preoccuparsi di leggerlo di nuovo quando lo si confronta con 2 poiché "sa" che non può essere cambiato. Tuttavia, un altro thread potrebbe averlo modificato. Quindi le ottimizzazioni di alcuni tipi devono essere disabilitate quando è richiesta la sincronizzazione tra i thread. Questo è ciò che fa volatile do.

Se i compilatori e le CPU non eseguivano ottimizzazioni ed eseguivano un programma esattamente come era stato scritto, non sarebbe mai necessario il volatile. La visibilità della memoria riguarda le ottimizzazioni nel codice (alcune fatte dal compilatore, alcune dalla CPU), non le cache.

+0

"Cache della CPU .. non hanno nulla a che fare con la visibilità della memoria" - Perché? Molti testi suggeriscono diversamente. Ad esempio, dalle Domande frequenti su JMM (http://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#synchronization): "Dopo aver chiuso un blocco sincronizzato, rilasciamo il monitor, che ha l'effetto di svuotare la cache nella memoria principale, in modo che le scritture fatte da questo thread possano essere visibili ad altri thread " –

+1

@EyalSchneider: Il JMM non sta parlando di alcuna implementazione effettiva ma di un sistema nozionale che * potrebbe * fare qualsiasi cosa. * Se * avessi cache che non erano hardware coerenti, dovresti scaricarle. Si noti che dice "ha l'effetto ** ** di svuotare la cache nella memoria principale", non che effettivamente svuota le cache. (E, in pratica, nessuna cache viene svuotata del tutto, vengono utilizzate solo le barriere di memoria che bypassano determinate ottimizzazioni della CPU come fetch speculativi e scritture postate.) –

+0

Grazie David, come hai detto se un thread leggeva 'j' e quindi un altro thread cambiarlo, il primo thread non lo noterà. Quindi il testo che ho citato è in realtà sbagliato? – MrROY

1

Penso che il testo che stai citando sia errato. L'intera idea del modello di memoria Java è di occuparsi delle complesse ottimizzazioni dell'hardware moderno software &, in modo che i programmatori possano determinare quali scritture sono visibili dalle rispettive letture in altri thread.

A meno che un programma in Java sia correttamente sincronizzato, non è possibile garantire che le modifiche apportate da un thread siano immediatamente visibili ad altri thread. Forse il testo si riferisce a un modello di memoria molto specifico (e debole).

L'utilizzo di variabili volatili è solo un modo per sincronizzare i thread e non è adatto a tutti gli scenari.

--Edit--

credo di aver capito la confusione ora ... Sono d'accordo con David Schwartz, partendo dal presupposto che:

1) "modifica una risorsa processo", l'attuale modificare della risorsa, non solo l'esecuzione di un'istruzione di scrittura scritta in un linguaggio di computer di alto livello.

2) "è immediatamente visibile per thread figlio" significa che altri thread sono in grado per vederlo; non significa che un thread nel tuo programma lo vedrà necessariamente. Potrebbe essere comunque necessario utilizzare gli strumenti di sincronizzazione per disabilitare le ottimizzazioni che ignorano l'effettivo accesso alla risorsa.

+0

Hai sbagliato e ragione. Hai ragione che le complesse ottimizzazioni dei moderni software e hardware devono essere affrontate. Ma ha chiesto informazioni sulle cache della CPU, non su "complesse ottimizzazioni". Le cache della CPU sono rese invisibili dall'hardware di coerenza della cache. Infatti, sulle moderne CPU Intel, lo scopo principale della cache L3 è quello di accelerare le operazioni inter-core (e su quasi tutte le CPU multi-core, uno scopo secondario della cache L2 è farlo). Se dovessi lavorare intorno a loro o svuotarli per sincronizzare i thread, renderebbero una delle cose che dovrebbero migliorare ancora peggio. –

+0

@DavidSchwartz: Non stavo parlando di cache particolari nella mia risposta. Ho appena sottolineato che il testo citato nella domanda è errato e fuorviante. –

+0

Direi che è corretto ma fuorviante. –

Problemi correlati