2013-05-01 2 views
7

So che in java, se si hanno più thread che accedono a una variabile che non è marcata come volatile, si potrebbe ottenere un comportamento imprevisto.Sia la parola chiave volatile C# che java si comportano allo stesso modo?

Esempio:

private boolean bExit; 

while(!bExit) { 
    checkUserPosition(); 
    updateUserPosition(); 
} 

Se si contrassegna la variabile bExit come voilatile, che avrebbe gaurantee che altri thread vedrà il valore più recente.

C# si comporta allo stesso modo?

Aggiornamento

Ad esempio, in C#, se si esegue questa operazione:

int counter = ...; 

for(...) 
{ 
    new Thread(delegate() 
    { 

     Interlocked.Decrement(ref counter); 
    } 
} 


if(counter == 0) 
{ 
    // halt program 
} 

In quanto sopra, in C#, devi segnare la variabile del contatore come volatili o questo funzionerà come previsto?

+1

Ogni * runtime * (modelli di memoria JVM o CLR) ha un diverso insieme di regole con alcune sovrapposizioni. Considera la ricerca di usi corretti (e non corretti) di 'volatile' in entrambe le lingue/runtime e confronti. – user2246674

+0

Il C# volatile è davvero riservato per l'utilizzo in applicazioni a bassa memoria e dovrebbe essere utilizzato solo come ultima risorsa in assoluto per trovare una documentazione in termini di C#: http://msdn.microsoft.com/en-us /library/x13ttww7(v=vs.71).aspx – Nomad101

+1

@ Nomad101 - Non sono sicuro di quale rapporto ci sia tra le applicazioni con memoria insufficiente e la parola chiave volatile. – hatchet

risposta

0

Se si contrassegna la variabile bExit come voilatile, che avrebbe gaurantee che altri thread vedranno il valore più recente. C# si comporta allo stesso modo?


Sì, ma tutto dipende da come si accede variabile condivisa. come esempio, se accedete al variyable in modo thread-safe come Interlocked.Decrement non sarà un problema anche senza usare voilatile.

volatile (C# Reference from MSDN)

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 sempre presente nel campo.

What is the "volatile" keyword used for?

+0

Quindi ho ragione nel capire che senza volatili, potresti ottenere risultati imprevisti quando leggi una variabile non volatile che è essere aggiornato i miei thread multipli? – loyalflow

+1

Ho letto che volatile in realtà non fa quello che molte persone pensano che faccia. Raccomando di leggere http://www.albahari.com/threading/part4.aspx#_The_volatile_keyword – hatchet

0

Devi essere un po 'attenti qui come hai scelto due tipi diversi nei vostri esempi. La mia regola generale è che volatile è meglio utilizzato con i booleani e con tutto il resto è probabilmente necessario un altro tipo di meccanismo di sincronizzazione. È molto comune in C# e java utilizzare un booleano volatile ad es. interrompere un loop o un'attività di esecuzione che ha una visibilità da più thread:

class Processor 
{ 
    private volatile Boolean _stopProcessing = false; 

    public void process() 
    { 
     do 
     { ... } 
     while (!_stopProcessing); 
    } 

    public void cancel() 
    { 
     _stopProcessing = true; 
    } 
} 

che questo funzionerebbe in C# o Java e in questo esempio la parola chiave volatile significa che la lettura nel metodo processo sarà dal valore corrente attuale e non un valore memorizzato nella cache. Il compilatore o la VM può scegliere altrimenti di consentire che il valore venga memorizzato nella cache poiché il ciclo in corso non modifica lo stesso processo.

Quindi la risposta è sì alla prima domanda.

Mentre è possibile utilizzare volatile su un file int questo solo aiuta se si sta solo leggendo, o scrivendo un singolo valore. Non appena fai qualcosa di più complesso, ad es.incrementando, hai bisogno di qualche altro tipo di sincronizzazione come il tuo uso di Interlocked. Nel tuo secondo esempio, tuttavia, stai ancora leggendo il valore del contatore senza alcuna sincronizzazione, quindi ti stai effettivamente affidando ad altri usi del contatore da sincronizzare (ad esempio con Interlock).

Nel tuo secondo esempio, sarebbe ancora meglio contrassegnare il tuo int come volatile, in questo modo puoi essere sicuro che stai ottenendo il valore corrente e non una versione cache. Tuttavia, l'utilizzo della sola volatile non è sufficiente perché la lettura nella parte inferiore potrebbe sovrapporsi a un decremento standard (contatore--) piuttosto che all'uso corretto di Interlocked.