CodeGym /Java kurs /Modul 2: Java Core /Tråder er ikke uavhengige! Synkronisert!

Tråder er ikke uavhengige! Synkronisert!

Modul 2: Java Core
Nivå , Lekse
Tilgjengelig

"Hei, Amigo! Vi har et universalmiddel - en kur mot alle sykdommer. Som vi allerede har sett, er ukontrollert trådbytte et problem."

"Hvorfor kan ikke trådene selv bestemme når de skal bytte til neste tråd? Gjøre alt de trenger å gjøre og så signalisere «Jeg er ferdig!»?"

"Å tillate tråder selv å kontrollere bytte ville være et enda større problem. Tenk deg at du har en dårlig skrevet kode, og tråden gir aldri fra seg CPU'en. Tilbake i dag, var det slik det fungerte. Og det var litt av et mareritt."

"Ok. Så hva er løsningen?"

" Blokkerer andre tråder.  Slik fungerer det."

Det ble klart at tråder forstyrrer hverandre når de prøver å bruke delte objekter og/eller ressurser . Akkurat som vi så i eksemplet med konsollutgang: det er én konsoll og alle trådene som sendes ut til den. Det er rotete.

Så en spesiell gjenstand ble oppfunnet: mutex . Det er som et skilt på en baderomsdør som sier «tilgjengelig / opptatt» . Den har to tilstander: objektet er tilgjengelig eller okkupert . Disse tilstandene kalles også «låst» og «ulåst».

Når en tråd trenger et objekt som deles med andre tråder, sjekker den mutexen som er knyttet til objektet. Hvis mutexen er låst opp, låser tråden den (merker den som «okkupert») og begynner å bruke den delte ressursen. Etter at tråden har gjort sin virksomhet, låses mutexen opp (merket som «tilgjengelig»).

Hvis tråden vil bruke objektet og mutexen er låst, vil tråden sove mens den venter. Når mutexen endelig er låst opp av den okkuperende tråden, vil tråden vår umiddelbart låse den og begynne å kjøre. Analogien med et baderomsdørskilt er perfekt.

"Så hvordan jobber jeg med en mutex? Trenger jeg å lage spesielle objekter?"

"Det er mye enklere enn som så. Javas skapere bygde denne mutexen inn i Object-klassen. Så du trenger ikke engang å lage den. Den er en del av hvert objekt. Slik 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;
}
}
}
Byttemetoden bytter ut verdiene til variablene navn1 og navn2.

Hva kan skje hvis det kalles opp fra to tråder samtidig?

Faktisk kodeutførelse Koden til den første tråden Koden til den andre tråden
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;
Bunnlinjen
Verdiene til variablene ble byttet to ganger, og returnerte til sine opprinnelige plasseringer.

Vær oppmerksom på søkeordet  synkronisert .

"Ja, hva betyr det?"

"Når en tråd går inn i en kodeblokk merket som synkronisert, låser Java-maskinen umiddelbart mutexen til objektet som er angitt i parentes etter ordet synkronisert. Ingen annen tråd kan gå inn i denne blokken før tråden vår forlater den. Så snart tråden vår forlater den. blokken som er merket synkronisert, låses mutex umiddelbart og automatisk opp og vil være tilgjengelig for innhenting av en annen tråd."

Hvis mutexen er opptatt, vil tråden vår stå stille og vente på at den frigjøres.

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

"Ja. Men hva tror du vil skje i denne saken?"

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-metodene deler samme mutex (det dette objektet).

Hva skjer hvis en tråd kaller swap-metoden og en annen tråd kaller swap2-metoden?

"Siden mutexen er den samme, vil den andre tråden måtte vente til den første tråden forlater den synkroniserte blokken. Så det vil ikke være noen problemer med samtidig tilgang."

"Godt gjort, Amigo! Det er det riktige svaret!"

Nå vil jeg påpeke at synkronisert kan brukes til å merke ikke bare kodeblokker, men også metoder. Her er hva det betyr:

Kode Hva skjer egentlig
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