C'è qualche vantaggio dell'utilizzo di volatili parola chiave in contrasto per utilizzare la classe Interlocked?
-
19-09-2019 - |
Domanda
In altre parole, posso fare qualcosa con un volatile variabile che non può essere risolto con una normale variabile e la classe Interlocked?
Soluzione
EDIT:domanda in gran parte riscritto
Per rispondere a questa domanda, mi sono tuffata un po ' più in la questione e ho scoperto un paio di cose su volatile
e Interlocked
che non ero a conoscenza.Vediamo di chiarire che, non solo per me, ma per questa discussione e le altre persone a leggere su questo:
volatile
di lettura/scrittura sono supposti per essere immune al riordino.Questo solo significa che la lettura e la scrittura, non non significa qualsiasi altra azione;- la volatilità non è costretto sulla CPU, cioè, a livello hardware (x86 utilizza acquisire e rilasciare le recinzioni su qualsiasi lettura/scrittura).Impedisce compilatore o CLR ottimizzazioni;
Interlocked
utilizza atomica istruzioni di montaggio per CompareExchange (cmpxchg
), Di incremento (inc
ecc);Interlocked
non utilizzare una serratura a volte:un blocco di hardware su sistemi multi processore;uni-sistemi a processore, non c'è nessun blocco di hardware;Interlocked
è diverso davolatile
in quanto utilizza un completo di recinzione, dove volatile utilizza un mezzo di recinzione.- Una lettura a seguito di una scrittura possono essere riordinate quando si utilizza
volatile
.Non può accadere conInterlocked
.VolatileRead
eVolatileWrite
hanno lo stesso riordino problema di come `volatile (link grazie a Brian Gedeone).
Ora che abbiamo le regole, siamo in grado di definire una risposta alla tua domanda:
- Tecnicamente:sì, ci sono cose che si possono fare con
volatile
che non si può fare conInterlocked
:- Sintassi:non si può scrivere
a = b
dovea
ob
è volatile, ma questo è ovvio; - Si può leggere un valore diverso dopo la scrittura di un volatile variabile a causa di riordino.Non si può fare questo con
Interlocked
.In altre parole:si può essere meno cassetta di sicurezza convolatile
poi si può essere conInterlocked
. - Prestazioni:
volatile
è più veloceInterlocked
.
- Sintassi:non si può scrivere
Dal punto di vista semantico:no, perché
Interlocked
fornisce semplicemente un superset di operazioni ed è più sicuro da usare in quanto si applica piena di scherma.Non si può fare nulla convolatile
che non si può fare conInterlocked
e si può fare un sacco conInterlocked
che non si può fare con volatili:static volatile int x = 0; x++; // non-atomic static int y = 0; Interlocked.Increment(y); // atomic
Campo di applicazione:sì, dichiarando una variabile
volatile
rende volatile per ogni singolo accesso.È impossibile che la forza di questo comportamento in qualsiasi altro modo, quindivolatile
non può essere sostituito conInterlocked
.Questo è necessario in situazioni in cui altre biblioteche, interfacce o hardware è in grado di accedere ai vostri variabile e aggiornare, in qualsiasi momento, o hai bisogno della versione più recente.
Se vuoi chiedere a me, questo ultimo bit è la reale necessità di volatile
e ideale in cui due processi condividono la memoria e la necessità di leggere o scrivere, senza chiusura.Per dichiarare una variabile come volatile
è molto più sicuro, in questo contesto, quindi, costringendo tutti i programmatori di utilizzare Interlocked
(che non è possibile forzare il compilatore).
EDIT:La seguente citazione è stata parte della mia originale risposta, lascio a ;-)
Una citazione dal Linguaggio Di Programmazione C# standard:
Per non volatile campi,ottimizzazione tecniche di considerare che riordino istruzioni può causare imprevisti e risultati imprevedibili in i programmi multithreading che l'accesso campi senza sincronizzazione come che ha fornito il lock-istruzione.Questi optimizationscan essere eseguita da il compilatore, dal runtime di sistema, o dall'hardware.Per campi volatili, tale riordino ottimizzazioni limitata:
Una lettura di un volatile campo è chiamato un volatile a leggere.Una lettura volatile dispone di :acquisire semantica";che è, è è garantito che si verificano prima di qualsiasi i riferimenti alla memoria che si verificano dopo nella sequenza di istruzioni.
Una scrittura di un campo volatile è chiamato scrittura volatile.Un scrittura volatile ha "comunicato semantica";che è, è garantito a succedere dopo la memoria riferimenti prima dell'istruzione di scrittura in di istruzioni in sequenza.
Aggiornamento: domanda in gran parte riscritto, corretto la mia risposta originale e aggiunto una "vera" risposta
Altri suggerimenti
Questo è un argomento abbastanza complesso. Trovo writeup di essere una delle fonti più definitive e precisare la ricerca multithreading concetti in .NET Framework che potrebbe aiutare a rispondere alla tua domanda.
Ma, al riassume rapidamente c'è un sacco di sovrapposizione tra la parola e la classe volatile
Interlocked
quanto riguarda il modo in cui possono essere utilizzati. E, naturalmente, entrambi vanno molto al di sopra e al di là di quello che si può fare con una variabile normale.
Sì - si può guardare direttamente il valore.
Finché si utilizza SOLO la classe Interlocked per accedere alla variabile quindi non c'è nessuna differenza.Cosa volatili non si dice al compilatore che la variabile è speciale e quando ottimizzazione non dovrebbe presumere che il valore non è cambiato.
Prende questo ciclo:
bool done = false;
...
while(!done)
{
... do stuff which the compiler can prove doesn't touch done...
}
Se si imposta done
per true
in un altro thread si aspetta che il ciclo termina.Tuttavia - se il fatto non è contrassegnato come volatile
quindi il compilatore ha la possibilità di rendersi conto che il codice di ciclo non potrà mai cambiare done
e si può ottimizzare il confronto per uscire.
Questa è una delle cose difficili circa la programmazione multithread - molte delle situazioni che sono problemi soltanto in determinate situazioni.
Non tenterò di essere un'autorità su questo argomento, ma mi raccomando che si prende un'occhiata a questo articolo dalla decantata Jon Skeet.
Anche prendere uno sguardo alla parte finale del questa risposta che dettaglia quanto volatile
deve essere utilizzato per.
Sì, è possibile guadagnare un po 'le prestazioni utilizzando una variabile volatile, invece di un blocco.
Lock è una barriera di memoria piena che può dare le stesse caratteristiche di una variabile volatile, così come molti altri. Come è già stato detto volatili solo assicura che gli scenari in multi-thread se una CPU modifica un valore nella linea di cache, l'altra CPU vede immediatamente il valore ma non assicurano alcuna bloccaggio semantica affatto.
La cosa è blocco è molto più potente di volatili e si dovrebbe utilizzare volatili quando si può evitare inutili le serrature.