C'è qualche vantaggio dell'utilizzo di volatili parola chiave in contrasto per utilizzare la classe Interlocked?

StackOverflow https://stackoverflow.com/questions/1701216

Domanda

In altre parole, posso fare qualcosa con un volatile variabile che non può essere risolto con una normale variabile e la classe Interlocked?

È stato utile?

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 da volatile 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 con Interlocked. VolatileRead e VolatileWrite 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 con Interlocked:
    1. Sintassi:non si può scrivere a = b dove a o b è volatile, ma questo è ovvio;
    2. 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 con volatile poi si può essere con Interlocked.
    3. Prestazioni: volatile è più veloce Interlocked.
  • 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 con volatile che non si può fare con Interlocked e si può fare un sacco con Interlocked 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, quindi volatile non può essere sostituito con Interlocked.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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top