"Hej, Amigo! Du kan huske, at Ellie fortalte dig om de problemer, der opstår, når flere tråde forsøger at få adgang til en delt ressource samtidigt, ja?"

"Ja."

"Sagen er, at det ikke er alt. Der er et andet lille problem."

En computer har som bekendt hukommelse, hvor data og kommandoer (kode) er gemt, samt en processor, der udfører disse kommandoer og arbejder med dataene. Processoren læser data fra hukommelsen, ændrer dem og skriver dem tilbage til hukommelsen. For at fremskynde beregningerne har processoren sin egen indbyggede "hurtige" hukommelse: cachen.

Processoren kører hurtigere ved at kopiere de hyppigst anvendte variabler og hukommelsesområder til sin cache. Så foretager den alle ændringerne i denne hurtige hukommelse. Og så kopierer den dataene tilbage til "langsom" hukommelse. Alt dette mens den langsomme hukommelse indeholder de gamle (uændrede!) variabler.

Det er her problemet opstår. En tråd ændrer en variabel , såsom isCancel eller isInterrupted i eksemplet ovenfor, men en anden tråd «kan ikke se denne ændring , fordi det skete i den hurtige hukommelse. Dette er en konsekvens af, at trådene ikke har adgang til hinandens cache. (En processor indeholder ofte flere uafhængige kerner, og trådene kan køre på fysisk forskellige kerner.)

Lad os huske gårsdagens eksempel:

Kode Beskrivelse
class Clock implements Runnable
{
private boolean isCancel = false;

public void cancel()
{
this.isCancel = true;
}

public void run()
{
while (!this.isCancel)
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
Tråden «ved ikke», at de andre tråde eksisterer.

I kørselsmetoden sættes variabelen isCancel i undertrådens cache, når den bruges første gang. Denne operation svarer til følgende kode:

public void run()
{
boolean isCancelCached = this.isCancel;
while (!isCancelCached)
{
Thread.sleep(1000);
System.out.println("Tick");
}
}

Kaldning af annulleringsmetoden fra en anden tråd vil ændre værdien af ​​isCancel i normal (langsom) hukommelse, men ikke i andre trådes cache.

public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clock.cancel();
}

"Hov! Og kom de med en smuk løsning til dette også, som med  synkroniseret ?"

"Du vil ikke tro det!"

Den første tanke var at deaktivere cachen, men det fik programmerne til at køre flere gange langsommere. Så dukkede en anden løsning op.

Det flygtige nøgleord blev født. Vi sætter dette søgeord før en variabeldeklaration for at angive, at dets værdi ikke må placeres i cachen. Mere præcist var det ikke, at det ikke kunne lægges i cachen, det var simpelthen, at det altid skulle læses fra og skrives til den normale (langsomme) hukommelse.

Sådan reparerer du vores løsning, så alt fungerer fint:

Kode Beskrivelse
class Clock implements Runnable
{
private volatile boolean isCancel = false;

public void cancel()
{
this.isCancel = true;
}

public void run()
{
while (!this.isCancel)
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
Den flygtige modifikator får en variabel til altid at blive læst fra og skrevet til normal hukommelse, der deles af alle tråde.
public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clock.cancel();
}

"Det er det?"

"Det var det. Enkelt og smukt."