Contents
volatile – La keyword che ipotizza sempre il peggio
La paranoia multithread
Benvenuti nel mondo di volatile. Questo non è un keyword da tutti i giorni. Se state pensando di usarlo per la vostra applicazione CRUD standard, per favore, tornate a scrivere new() e ToList().
volatile è per i paranoici, per coloro che non si fidano minimamente del compilatore o della cache della CPU quando si tratta di operazioni multithreading. Dici al compilatore: “Ehi! Non fidarti! Ogni volta che leggi questa variabile, vai direttamente nella memoria principale. Non osare usare la cache locale, perché chissà, magari l’altro thread l’ha cambiata un nanosecondo fa!”
È l’equivalente del tennista che mette in discussione ogni singola chiamata dell’arbitro, anche se il colpo era palesemente out. Non si fida di nessuno. E in un ambiente multithread, a volte, non fidarsi è l’unica strategia.
“In the end, you should always do the right thing, even if it’s hard.” – Roger Federer (leggenda del tennis).
In C#, fare la cosa giusta (usare i meccanismi di sincronizzazione di
.NET) è spesso più difficile che usarevolatile. Ma a volte, quando la posta in gioco è alta e non puoi fidarti della CPU,volatileè il tuo blocco difensivo. Attenzione:volatilenon è un sostituto per i lock. È come dire al tuo attaccante di fare pressing: non è una difesa completa, ma aiuta.
La memoria sotto sorveglianza
Quando si tratta di un flag che può essere letto da un thread e scritto da un altro, e non volete usare un lock (perché rallenterebbe troppo, o è un contesto specifico):
C#
public class Stopper
{
// Il keyword volatile obbliga la CPU a ricaricare questo campo dalla
// memoria ogni volta che viene letto, e a scaricarlo subito dopo averlo scritto.
// Senza di esso, un altro thread potrebbe leggere un valore in cache obsoleto.
private volatile bool _stopRequested = false;
public void RequestStop()
{
// Scrive immediatamente in memoria
_stopRequested = true;
}
public void WorkerMethod()
{
// Legge sempre dalla memoria principale per vedere se c'è una richiesta
while (!_stopRequested)
{
// Lavora sodo come un operaio
Thread.Sleep(50);
}
Console.WriteLine("Worker interrotto.");
}
}
Ricorda, volatile non garantisce operazioni atomiche complesse. Per quello, avrai bisogno di armi più pesanti (come lock o Interlocked). Ma per un semplice bool o int, è come un rapido “sguardo furtivo” alla memoria principale.
