2010-08-21 8 views
13

Mentre leggo sempre più in profondità il significato della parola chiave volatile, continuo a dire a me stesso "questa è la via dell'implementazione , questo non dovrebbe far parte di un linguaggio di programmazione di alto livello".
Voglio dire, il fatto che le CPU nascondano i dati dovrebbe essere interessante per il compilatore JIT, non per il programmatore C#.C# - È "volatile" davvero necessario come parola chiave?

Un'alternativa considerevole potrebbe essere un attributo (ad esempio, VolatileAttribute).

Cosa ne pensi?

+0

+1 Penso che VolatileAttribute sia ok in questa situazione. Ma non so perché la MS ne fa una parola chiave. –

+0

Si suppone che C# sia simile a C++ e che C++ abbia già "volatile". Dato che hanno deciso che avevano bisogno di questa funzionalità (e sono d'accordo), e la parola chiave è già nel set "simile", perché non usarla solo? – Blindy

+0

@Blindy: C++ volatile ha un diverso modello di utilizzo, quindi non mi sarei tenuto a mente. –

risposta

2

IIIRC, in C++ volatile riguardava principalmente l'I/O mappato in memoria anziché la cache. Se leggi due volte la stessa porta ottieni risposte diverse. Tuttavia, sarei d'accordo con la tua valutazione sul fatto che questo è più chiaramente espresso in C# come attributo.

D'altra parte, la maggior parte degli usi effettivi del volatile in C# può essere meglio intesa come blocco del thread in ogni caso, quindi la scelta di volatile può essere un po 'sfortunata.

Edit: Giusto per aggiungere: due collegamenti per dimostrare che in C/C++ `volatile è explicitlynot per il multithreading.

3

L'utilizzo di un attributo sarebbe accettabile, se fosse il contrario, cioè, il compilatore assumerebbe che tutte le variabili sono volatili, a meno che non sia esplicitamente contrassegnato con un attributo che dice che è sicuro. Quello sarebbe incredibilmente determental alle prestazioni.

Quindi si presume che, poiché il valore di una variabile modificato al di fuori della vista del compilatore sia un'aberrazione, il compilatore presupporrà che non si sta verificando.

Tuttavia, che potrebbe accadere in un programma in modo che la lingua stessa deve avere un modo di dimostrarlo.

Inoltre, sembra confuso riguardo ai "dettagli di implementazione". Il termine si riferisce a cose che il compilatore fa alle tue spalle. Questo non è il caso qui. Il codice sta modificando un varaible al di fuori della vista del compilatore. Dato che è il tuo codice, sarà sempre vero. Quindi il langauge deve essere in grado di indicarlo.

8

Penso che tu sia stato seguito. Tutto il materiale tecnico sulla memorizzazione nella cache ecc. Fa parte di un tentativo di spiegarlo in termini di basso livello. La descrizione funzionale per volatile sarebbe "Potrei essere condiviso". Dato che per impostazione predefinita nulla può essere condiviso tra i thread, questo non è del tutto strano. E penso che sia abbastanza fondamentale da giustificare una parola chiave su un attributo, ma suppongo sia stato largamente influenzato da decisioni storiche (C++)

Un modo per sostituirlo/ottimizzarlo è con le chiamate VolatileRead() e VolatileWrite(). Ma è ancora più "implementazione".

5

Beh, sono certamente d'accordo, è piuttosto orribile che un tale dettaglio di implementazione sia esposto. È tuttavia lo stesso tipo di dettaglio esposto dalla parola chiave lock. Siamo ancora molto lontani dallo che il generatore di bug sia completamente rimosso dal nostro codice.

I ragazzi dell'hardware hanno molto lavoro da fare. La parola chiave volatile conta un sacco di core CPU con un modello di memoria debole.Il mercato non è stato gentile con loro, l'Alpha e l'Itanium non hanno funzionato bene. Non sono esattamente sicuro del perché, ma ho il sospetto che la difficoltà di scrivere codice thread solido per questi core abbia molto a che fare con questo. Sbagliare è piuttosto un incubo per il debug. La verbosità nella documentazione di MSDN Library per volatile si applica a questi tipi di processori, altrimenti è abbastanza inappropriata per i core x86/x64 e fa sembrare che la parola chiave stia facendo molto di più di quanto non faccia realmente. Volatile impedisce semplicemente di memorizzare i valori delle variabili nei registri della CPU su quei core.

Sfortunatamente, volatile è ancora importante per i core x86 in molto selezionare le circostanze. Non ho ancora trovato alcuna prova che sia importante su core x64. Per quanto ne so, e supportato dal codice sorgente in SSCLI20, l'istruzione Opcodes.Volatile è un no-op per il jitter x64, non modifica né lo stato del compilatore né emette alcun codice macchina. Sta andando nel modo giusto.

Il consiglio generico è che ovunque tu stia contemplando volatile, l'utilizzo del blocco o di una delle classi di sincronizzazione dovrebbe essere la tua prima considerazione. Evitandoli per cercare di ottimizzare il tuo codice è una micro-ottimizzazione, sconfitta dalla quantità di sonno che perderai quando il tuo programma presenta problemi di problemi di thread.

+0

I metodi Thread.VolatileRead e Thread.VolatileWrite includono chiamate a Thread.MemoryBarrier. Se la parola chiave volatile è un no-op, ciò significherebbe che la parola chiave volatile funziona in modo diverso rispetto ai metodi VolatileRead e VolatileWrite. Yikes! (E no, Thread.MemoryBarrier non dovrebbe essere un no-op. Le CPU x86 e x64 hanno buffer di memoria che possono comportare il riordino del negozio seguito dal carico. Il negozio seguito dal carico è centrale per Dekker, quindi le interruzioni di Dekker su questi arch le barriere di memoria non vengono utilizzate. Una buona risorsa è http://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf.) –

+0

Non includono una barriera, il titanio era molto più volubile di così. Flushing in sospeso letture e scritture era separato. C'era anche una merda. Penso, non sono mai stato consapevolmente entro un raggio di 500 miglia da uno. Non sento come una perdita. –

2

volatile in C# emette le barriere corrette, o recinzioni, che sarebbero importanti per il programmatore che esegue il lavoro multi-thread. Ricordare che il compilatore, il runtime e il processore possono riordinare le letture/scritture in una certa misura (ognuna ha le proprie regole). Anche se CLR 2.0 ha un modello di memoria più forte che specifica CLI ECMA, il modello di memoria CLR non è ancora il modello di memoria più rigido, quindi è necessario il numero volatile in C#.

Come attributo, non penso che sia possibile utilizzare gli attributi all'interno di un corpo del metodo, quindi la parola chiave è necessaria.