2012-05-17 8 views
22

Secondo MSDN:Volatile Viole il suo lavoro principale?

La parola chiave volatile indica che un campo potrebbe essere modificata multipli thread che stanno eseguendo contemporaneamente. I campi che sono dichiarati volatili non sono soggetti alle ottimizzazioni del compilatore che assume l'accesso da un singolo thread. Ciò garantisce che il valore più aggiornato di sia presente nel campo in ogni momento.

Si prega di notare l'ultima frase:

Questo assicura che il massimo valore up-to-date è presente nel campo in ogni momento.

Tuttavia, c'è un problema con questa parola chiave.

Sono read che possa modificare l'ordine delle istruzioni:

First instruction  Second instruction   Can they be swapped? 
Read       Read       No 
Read       Write      No 
Write      Write       No 
Write      Read       Yes! <---- 

Ciò significa John imposta un valore a un campo volatile, e successivamente Paolo vuole leggere il campo, Paul sta ottenendo il valore vecchio!

Cosa sta succedendo? Non è il lavoro principale?

So che ci sono altre soluzioni, ma la mia domanda riguarda la parola chiave volatile.

Devo (come programmatore) evitare l'utilizzo di questa parola chiave, a causa di un comportamento così strano?

+1

Da dove viene questo tavolo? – Corbin

+0

@Corbin premere sul collegamento 'ive read'. –

+0

Ah ok. Questo ha senso allora. Un secondo e elaborerò. Edit: Ok, riprendo quello. Ha senso nella mia testa, ma non riesco a spiegarlo>. <. – Corbin

risposta

7

La documentazione MSDN è errata. Questo non è certamente ciò che fa volatile. La specifica C# ti dice esattamente cosa fa volatile e ottenere una "nuova lettura" o una "scrittura impegnata" non è una di queste. La specifica è corretta volatile garantisce solo acquisizioni-recinzioni su letture e release-fence su scritture. Questi sono definiti come di seguito.

  • acquisiscono-recinto: Una barriera di memoria in cui altre letture e le scritture non sono autorizzati a muoversi prima la recinzione.
  • release-fence: una barriera di memoria in cui altre letture e scritture non sono autorizzati a spostarsi dopo il il recinto.

Proverò a spiegare la tabella utilizzando la mia notazione a freccia. Una freccia ↓ segnerà una lettura volatile e una freccia ↑ contrassegnerà una scrittura volatile. Nessuna istruzione può spostarsi attraverso la punta della freccia. Pensa alla punta della freccia come a spingere tutto via.

Nell'analisi seguente verrà utilizzato per le variabili; x e . Presumo anche che siano contrassegnati come volatile.

Caso # 1

Notate come il posizionamento della freccia dopo la lettura del x impedisce la lettura di y di muoversi in su. Si noti inoltre che la volatilità di è irrilevante in questo caso.

var localx = x; 
↓ 
var localy = y; 
↓ 

Caso # 2

Notate come il posizionamento della freccia dopo la lettura del x impedisce la scrittura per y di muoversi in su. Si noti inoltre che la volatilità di uno dei numeri x o , ma non entrambi, potrebbe essere stata omessa in questo caso.

var localx = x; 
↓ 
↑ 
y = 1; 

Caso # 3

Notate come il posizionamento della freccia prima che la scrittura per y impedisce la scrittura per x di muoversi verso il basso. Si noti che la volatilità di x è irrilevante in questo caso.

↑ 
x = 1; 
↑ 
y = 2; 

Caso # 4

Si noti che non v'è alcuna barriera tra la scrittura per x e la lettura di y. Per questo motivo, la scrittura su x può essere spostata verso il basso o la lettura di può essere spostata verso l'alto. Ciascun movimento è valido. Questo è il motivo per cui le istruzioni nel caso di lettura-scrittura possono essere scambiate.

↑ 
x = 1; 
var localy = y; 
↓ 

Notevole Menzioni

E 'anche importante notare che:

  • hardware x86 ha semantica volatili in scrittura.
  • L'implementazione di Microsoft della CLI (e sospetto anche di Mono) ha una semantica volatile sulle scritture.
  • La specifica ECMA non ha semantica volatile sulle scritture.
+0

lo so, vedere la mia domanda su questo argomento http://stackoverflow.com/questions/10589654/half-fences-and-full-fences –

+0

hhh hai risposto già lì ..... lol. Ho ancora bisogno di controllare un po 'di conoscenza prima di controllare una risposta .... (per la domanda di collegamento) –

+0

@RoyiNamir: Dai un'occhiata a [questo] (http://stackoverflow.com/q/10281044/158779) domanda dove analizzo il pattern di blocco a doppio controllo usando la notazione a freccia che ho trovato. La notazione a freccia aiuta davvero quando si tenta di visualizzare ciò che può e non può accadere. –

18

Bene, hai ragione. È più elaborato in Joseph Albahari che filtra book/article.

La documentazione MSDN indica che l'uso della parola chiave volatile garantisce che il valore più up-to-data è presente nel campo in ogni momento. Questo non è corretto, poiché come abbiamo visto, una scrittura seguita da una lettura può essere riordinata.

http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword

Dovrei (come programmatore) necessario evitare che usando questa parola chiave, a causa di tale comportamento strano?

Si deve essere usato solo dopo aver conosciuto questo comportamento weired. Non dovrebbe essere usato come parola chiave Magic per recuperare gli ultimi valori sempre in ambiente multithread.

IMO, l'utilizzo di parole chiave volatili deve essere evitato in quanto è difficile trovare bug probabili.

+3

perché msn non scrive questo comportamento strano? perché devo sentirlo da Joseph? –

+4

Non lo so. MSDN è effettivamente errato in vari punti. Posso vedere i commenti degli utenti sottolineando questo. Nell'articolo di Joseph, la conclusione è supportata da un esempio adatto che puoi provare tu stesso. – Tilak

4

Un altro punto sollevato da Joseph Albahari è che l'architettura di processo può avere un impatto negativo, in particolare AMD, in particolare può causare lo scambio di valori.

Dal momento che probabilmente non si ha idea di quale tipo di sistema verrà eseguito nella propria produzione in modo ottimale, evitare sempre la parola chiave volatile.

anche un po 'fuori tema si dovrebbe sempre evitare di classe ReaderWriterLock come sotto carico pesante su sistemi multiprocessore questo può consentire a più blocchi di scrittura please see here da adottare contemporaneamente che causerà applicazione si blocca, che sarà estremamente difficile causa principale

+0

'ReaderWriterLockSlim' è anche menzionato nel post che hai collegato, probabilmente è meglio menzionarlo anche qui. –