"Hei, Amigo! Du husker at Ellie fortalte deg om problemene som oppstår når flere tråder prøver å få tilgang til en delt ressurs samtidig, ja?"

"Ja."

"Tekken er at det ikke er alt. Det er et annet lite problem."

Som du vet har en datamaskin minne hvor data og kommandoer (kode) er lagret, samt en prosessor som utfører disse kommandoene og jobber med dataene. Prosessoren leser data fra minnet, endrer det og skriver det tilbake til minnet. For å få fart på beregningene har prosessoren sitt eget innebygde "raske" minne: cachen.

Prosessoren kjører raskere ved å kopiere de mest brukte variablene og minneområdene til hurtigbufferen. Da gjør den alle endringene i dette raske minnet. Og så kopierer den dataene tilbake til «sakte» minne. Alt dette mens det langsomme minnet inneholder de gamle (uendrede!) variablene.

Det er her problemet oppstår. En tråd endrer en variabel , for eksempel isCancel eller isInterrupted i eksemplet ovenfor, men en andre tråd «ser ikke denne endringen , fordi den skjedde i det raske minnet. Dette er en konsekvens av at trådene ikke har tilgang til hverandres cache. (En prosessor inneholder ofte flere uavhengige kjerner og trådene kan kjøre på fysisk forskjellige kjerner.)

La oss 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 «vet ikke» at de andre trådene finnes.

I kjøringsmetoden legges variabelen isCancel inn i undertrådens cache når den brukes for første gang. Denne operasjonen tilsvarer følgende kode:

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

Å kalle avbryt- metoden fra en annen tråd vil endre verdien til isCancel i normalt (tregt) minne, men ikke i andre tråders cacher.

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

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

"Wow! Og kom de opp med en vakker løsning for dette også, som med  synkronisert ?"

"Du vil ikke tro det!"

Den første tanken var å deaktivere cachen, men dette gjorde at programmer gikk flere ganger tregere. Så dukket det opp en annen løsning.

Det flyktige nøkkelordet ble født. Vi setter dette søkeordet foran en variabeldeklarasjon for å indikere at verdien ikke må legges inn i hurtigbufferen. Mer presist var det ikke det at det ikke kunne legges inn i cachen, det var rett og slett at det alltid måtte leses fra og skrives til det vanlige (langsomme) minnet.

Slik fikser du løsningen vår slik at alt fungerer bra:

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 flyktige modifikatoren fører til at en variabel alltid leses fra og skrives til normalt minne som deles av alle tråder.
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 er det. Enkelt og vakkert."