Lettura this question, volevo testare se potevo dimostrare la non-atomicità di letture e scritture su un tipo per il quale l'atomicità di tali operazioni non è garantita.Perché questo codice non dimostra la non-atomicità delle letture/scritture?
private static double _d;
[STAThread]
static void Main()
{
new Thread(KeepMutating).Start();
KeepReading();
}
private static void KeepReading()
{
while (true)
{
double dCopy = _d;
// In release: if (...) throw ...
Debug.Assert(dCopy == 0D || dCopy == double.MaxValue); // Never fails
}
}
private static void KeepMutating()
{
Random rand = new Random();
while (true)
{
_d = rand.Next(2) == 0 ? 0D : double.MaxValue;
}
}
Con mia sorpresa, l'affermazione si è rifiutata di fallire anche dopo ben tre minuti di esecuzione. Cosa dà?
- Il test non è corretto.
- Le specifiche caratteristiche di temporizzazione del test rendono improbabile/impossibile che l'affermazione fallisca.
- La probabilità è così bassa che devo eseguire il test per molto più tempo per renderlo probabile che si inneschi.
- Il CLR offre maggiori garanzie di atomicità rispetto alle specifiche C#.
- Il mio sistema operativo/hardware offre maggiori garanzie rispetto al CLR.
- Qualcos'altro?
Naturalmente, non intendo fare affidamento su alcun comportamento che non sia esplicitamente garantito dalle specifiche, ma vorrei una comprensione più approfondita del problema.
FYI, ho fatto questo su entrambi Debug e Release (cambiando Debug.Assert
a if(..) throw
) profili in due ambienti separati:
- di Windows 7 64-bit + .NET 3.5 SP1
- di Windows XP a 32 bit + NET 2,0
EDIT: per escludere la possibilità di commento di John Kugelman "il debugger non è Schrödinger-safe" essere il problema, ho aggiunto la linea someList.Add(dCopy);
al metodo KeepReading
e veri ha dimostrato che questo elenco non vedeva un singolo valore obsoleto dalla cache.
MODIFICA: Sulla base del suggerimento di Dan Bryant: l'utilizzo di long
invece di double
lo interrompe praticamente all'istante.
La mia ipotesi (ed è proprio così) è la # 3. – AakashM
Controllerei l'IL per assicurarmi che il compilatore non abbia giocato alcun trucco, ma a parte questo non ho ottenuto nulla. Mi aspetto che questo si interrompa su una macchina a 32 bit. – mquander
Aumentare il numero di thread di scrittura: provare a mantenere i thread N + 1 in esecuzione su un sistema N-core. –