CodeGym /Java kursus /Modul 2: Java Core /Tråde er ikke uafhængige! Synkroniseret!

Tråde er ikke uafhængige! Synkroniseret!

Modul 2: Java Core
Niveau , Lektie
Ledig

"Hej, Amigo! Vi har et universalmiddel - en kur mod alle sygdomme. Som vi allerede har set, er ukontrolleret trådskift et problem."

"Hvorfor kan trådene ikke selv bestemme, hvornår de skal skifte til den næste tråd? Gør alt, hvad de skal gøre og signaler derefter, "Jeg er færdig!"?"

"At lade tråde selv styre switching ville være et endnu større problem. Antag, at du har en dårligt skrevet kode, og tråden aldrig overgiver CPU'en. Dengang fungerede det sådan. Og det var noget af et mareridt."

"Okay. Hvad er så løsningen?"

" Blokerer andre tråde.  Sådan fungerer det."

Det blev klart, at tråde interfererer med hinanden, når de forsøger at bruge delte objekter og/eller ressourcer . Ligesom vi så i eksemplet med konsoludgang: Der er én konsol og alle trådene output til den. Det er rodet.

Så en speciel genstand blev opfundet: mutexen . Det er som et skilt på en badeværelsesdør, hvor der står «tilgængelig / optaget» . Det har to tilstande: objektet er tilgængeligt eller optaget . Disse tilstande kaldes også «låst» og «ulåst».

Når en tråd har brug for et objekt, der deles med andre tråde, kontrollerer den mutex, der er knyttet til objektet. Hvis mutex'en er låst op, låser tråden den (markerer den som «optaget») og begynder at bruge den delte ressource. Efter at tråden har gjort sin forretning, låses mutex'en op (markeret som «tilgængelig»).

Hvis tråden vil bruge objektet og mutex'en er låst, så sover tråden mens den venter. Når mutex'en endelig er låst op af den optagede tråd, vil vores tråd straks låse den og begynde at køre. Analogien med et badeværelsesdørskilt er perfekt.

"Så hvordan arbejder jeg med en mutex? Skal jeg lave specielle objekter?"

"Det er meget enklere end som så. Javas skabere indbyggede denne mutex i Object-klassen. Så du behøver ikke engang at oprette den. Det er en del af hvert objekt. Sådan fungerer det hele:"

Kode Beskrivelse
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Swap-metoden bytter værdierne af variablerne navn1 og navn2.

Hvad kan der ske, hvis det kaldes fra to tråde på samme tid?

Faktisk kodeudførelse Koden for den første tråd Kode for den anden tråd
String s1 = name1; //Ally
name1 = name2; //Lena
name2 = s1; //Ally

String s2 = name1; //Lena
name1 = name2; //Ally
name2 = s2; //Lena
String s1 = name1;
name1 = name2;
//other thread is running
name2 = s1;
//the thread waits until the mutex is unlocked

String s2 = name1;
name1 = name2;
//other thread is running
//other thread is running
name2 = s2;
Bundlinjen
Værdierne af variablerne blev byttet to gange, og vendte tilbage til deres oprindelige pladser.

Vær opmærksom på søgeordet  synkroniseret .

"Ja, hvad betyder det?"

"Når en tråd indtaster en kodeblok, der er markeret som synkroniseret, låser Java-maskinen øjeblikkeligt mutexet for objektet angivet i parentes efter ordet synkroniseret. Ingen anden tråd kan indtaste denne blok, før vores tråd forlader den. Så snart vores tråd forlader den. blokken, der er markeret som synkroniseret, låses mutexen øjeblikkeligt og automatisk op og vil være tilgængelig til at blive erhvervet af en anden tråd."

Hvis mutex'en er optaget, vil vores tråd stå stille og vente på, at den frigøres.

"Så enkelt og så elegant. Det er en smuk løsning."

"Ja. Men hvad tror du, der vil ske i denne sag?"

Kode Beskrivelse
class MyClass
{
private String name1 = "Ally";
private String name2 = "Lena";

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}

public void swap2()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
}
Swap- og swap2-metoderne deler samme mutex (det dette objekt).

Hvad sker der, hvis en tråd kalder swap-metoden og en anden tråd kalder swap2-metoden?

"Da mutex'en er den samme, vil den anden tråd skulle vente, indtil den første tråd forlader den synkroniserede blok. Så der vil ikke være nogen problemer med samtidig adgang."

"Godt gået, Amigo! Det er det rigtige svar!"

Nu vil jeg gerne påpege, at synkroniseret kan bruges til at markere ikke kun kodeblokke, men også metoder. Her er hvad det betyder:

Kode Hvad sker der virkelig
class MyClass
{
private static String name1 = "Ally";
private static String name2 = "Lena";

public synchronized void swap()
{
String s = name1;
name1 = name2;
name2 = s;
}

public static synchronized void swap2()
{
String s = name1;
name1 = name2;
name2 = s;
}
}
class MyClass
{
private static String name1 = "Ally";
private static String name2 = "Lena";

public void swap()
{
synchronized (this)
{
String s = name1;
name1 = name2;
name2 = s;
}
}

public static void swap2()
{
synchronized (MyClass.class)
{
String s = name1;
name1 = name2;
name2 = s;
}
}
Kommentarer
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION