Qualcuno può spiegarmi quali sono i vantaggi e gli svantaggi dei due diversi approcci?Java sembra supportare i campi volatili di tipo long mentre C# no - Quali sono le ragioni alla base di questo?
risposta
Quando un double
o long
in Java è volatile
, §17.7 of the Java Language Specification richiede che vengano letti e scritti atomicamente. Quando non sono volatili, possono essere scritti in più operazioni. Ciò può risultare, ad esempio, nei 32 bit superiori di un lungo contenente un nuovo valore, mentre i 32 bit inferiori contengono ancora il vecchio valore.
Le letture e le scritture atomiche sono più semplici per un programmatore con cui ragionare e scrivere codice corretto con. Tuttavia, il supporto per le operazioni atomiche potrebbe imporre un onere agli implementatori VM in alcuni ambienti.
Immagino che si tratti di ciò che il modello di memoria può garantire. Non conosco una grande quantità del modello di memoria CLI (che C# deve usare), ma so che garantirà 32 bit ... ma non 64 (anche se garantirà un riferimento a 64 bit su x64 - le regole complete si trovano al §17.4.3 dell'ECMA 334v4). Quindi non può essere volatile
. Hai comunque i metodi Interlocked
, ad esempio (come long Interlocked.Exchange(ref long,long)
e long Interlocked.Increment(ref long)
ecc.).
Suppongo che i long non possano essere volatili in C# perché sono più grandi di 32 bit e non è possibile accedervi in un'operazione atomica. Anche se non sarebbero memorizzati in un registro o nella cache della CPU, poiché è necessario più di un'operazione per leggere o scrivere il valore, è possibile che un thread legga il valore mentre un altro è in fase di scrittura.
Credo che ci sia una differenza tra il modo in cui Java implementa i campi volatili e come funziona DotNet, ma non sono sicuro dei dettagli. Java potrebbe utilizzare un blocco sul campo per prevenire il problema che ha C#.
Non conosco il motivo per cui volatile non può essere applicato a 64-bit ints in C#, ma è possibile utilizzare Thread.VolatileWrite per fare ciò che si desidera in C#. La parola chiave volatile è solo zucchero sintattico per questa chiamata.
estratto:
Nota: In C#, utilizzando il modificatore volatile, su un campo garantisce che tutti gli accessi a quel campo utilizza Thread.VolatileRead o Thread.VolatileWrite.
Lo zucchero sintattico (parola chiave) si applica a 32 bit int, ma è possibile utilizzare le chiamate di metodo effettive su 64 bit inte.
Tuttavia, è strano che il codice non ti consenta di specificare un campo volatile a 64 bit quando specifichi anche che la piattaforma sia x64. –
La CLI dovrebbe funzionare indipendentemente dalla piattaforma sottostante, quindi non vuole fare promesse che dipendono da ciò su cui si sta eseguendo. –