Lås og Betingelse
I Java er standard synkronisering baseret på nøgleordet synchronized og indbyggede monitorobjekter. I visse tilfælde kan synchronized dog være utilstrækkelig, især når der kræves større fleksibilitet i trådhåndtering.
Generel beskrivelse
Lock-interfacet og Condition-interfacet, introduceret i pakken java.util.concurrent.locks, tilbyder avancerede muligheder for trådhåndtering.
På dette billede kan du se, at første tråd optager låsen ved hjælp af lock()-metoden, og på dette tidspunkt kan en anden tråd ikke optage den samme lås. Så snart al koden inden for låsen er udført, kaldes unlock()-metoden, og låsen frigives. Først derefter kan anden tråd optage låsen.
Forskel
Forskellen mellem disse to interfaces er, at Lock-implementeringer er et højniveau alternativ til synchronized-blokke, og Condition-interface-implementeringer er et alternativ til notify()/wait()-metoderne. Begge disse interfaces er en del af pakken java.util.concurrent.locks.
Virkelige eksempler
Forestil dig, at du administrerer en kø til tilmelding til et arrangement. For at forhindre overløb og sikre korrekt sædetildeling, skal du bruge blokeringsmekanismer og betingelser for at holde strømmen af nye tilmeldinger ventende, indtil en ledig plads bliver tilgængelig.
ReentrantLock-klassen
ReentrantLock klassen fra java.util.concurrent.locks pakken er en implementering af Lock interfacet. Den giver funktionalitet til eksplicit håndtering af låse.
De vigtigste metoder i ReentrantLock:
lock(): Optager en lås;unlock(): Frigiver låsen;tryLock(): Forsøger at optage låsen og returnerer true, hvis det lykkes;tryLock(long timeout, TimeUnit unit): Forsøger at optage låsen i den angivne tid;newCondition(): Opretter en betingelse for den aktuelleLock.
Main.java
12345678910111213141516171819202122232425262728293031package com.example; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Main { // Creating a ReentrantLock object private final Lock lock = new ReentrantLock(); private int count = 0; // Method to increment the `count` variable public void increment() { lock.lock(); // Acquiring the `lock` try { count++; System.out.println("Count incremented to: " + count); } finally { lock.unlock(); // Releasing the `lock` } } public static void main(String[] args) { Main example = new Main(); // Runnable task to call the increment method Runnable task = example::increment; // Starting multiple threads to execute the task for (int i = 0; i < 5; i++) { new Thread(task).start(); } } }
Som du kan se, anvender vi låsning med increment() i metoden Lock. Når en tråd går ind i metoden, optager den låsen med lock.lock(), udfører derefter koden, og i finally-blokken frigiver vi låsen med lock.unlock(), så andre tråde kan få adgang.
Vi frigiver låsen i finally-blokken af en grund, nemlig at denne blok næsten altid bliver udført, selv ved undtagelser, undtagen når programmet afsluttes.
Condition-interface
Vi kan kun oprette et Condition-objekt med binding til en specifik Lock-implementering. Af denne grund vil Condition-metoderne kun påvirke låsningen af netop denne Lock-implementering.
Main.java
12private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition();
De vigtigste metoder for Condition:
await(): Venter på et signal fra en anden tråd;signal(): Låser én tråd op, som venter på en betingelse;signalAll(): Låser alle tråde op, der venter på betingelsen.
Main.java
12345678910111213141516private final ReentrantLock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private boolean ready = false; public void waitForCondition() throws InterruptedException { lock.lock(); // Acquire the `lock` try { while (!ready) { // Check if the condition is not met System.out.println("Waiting..."); // Print a waiting message condition.await(); // Wait for the condition to be signaled } System.out.println("Condition met!"); // Print a message when the condition is met } finally { lock.unlock(); // Release the `lock` } }
Metoden waitForCondition() blokerer tråden, indtil variablen ready bliver true, hvilket signalerer, at betingelsen er opfyldt. Når betingelsen er opfyldt, fortsætter tråden med at køre og viser beskeden “Condition met!”
Når metoden await() kaldes, bliver tråden pauset og frigiver også låsen, den har optaget. Når tråden vågner op, skal den optage låsen igen, og først derefter vil den begynde at udføre!
Kodeeksempel
Lad os nu se et eksempel på brug af ReentrantLock og Condition til at håndtere tilmelding til et arrangement:
Et kort klip fra videoen
Låsning med ReentrantLock: Metoden register() optager låsen med lock.lock() for at forhindre, at flere tråde udfører koden samtidigt.
Betingelse med Condition: Hvis der ikke er ledige pladser, kalder tråden spaceAvailable.await() for at vente, indtil der er plads tilgængelig.
Frigiv lås: Når en tråd har frigivet plads ved at bruge metoden cancel(), kalder den spaceAvailable.signalAll() for at underrette alle ventende tråde.
Undtagelseshåndtering: Brug af try-finally blokke sikrer, at låsen frigives, selv hvis en undtagelse opstår.
Brugen af Lock og Condition i Java muliggør mere fleksibel kontrol over tråde og synkronisering end den traditionelle synchronized-mekanisme. Dette er især nyttigt i komplekse scenarier, hvor mere præcis kontrol over tråde og ventebetingelser er påkrævet.
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat
Can you explain the main differences between Lock and Condition in Java?
How does ReentrantLock improve thread management compared to synchronized blocks?
Can you provide a simple example of using Condition with ReentrantLock?
Awesome!
Completion rate improved to 3.33
Lås og Betingelse
Stryg for at vise menuen
I Java er standard synkronisering baseret på nøgleordet synchronized og indbyggede monitorobjekter. I visse tilfælde kan synchronized dog være utilstrækkelig, især når der kræves større fleksibilitet i trådhåndtering.
Generel beskrivelse
Lock-interfacet og Condition-interfacet, introduceret i pakken java.util.concurrent.locks, tilbyder avancerede muligheder for trådhåndtering.
På dette billede kan du se, at første tråd optager låsen ved hjælp af lock()-metoden, og på dette tidspunkt kan en anden tråd ikke optage den samme lås. Så snart al koden inden for låsen er udført, kaldes unlock()-metoden, og låsen frigives. Først derefter kan anden tråd optage låsen.
Forskel
Forskellen mellem disse to interfaces er, at Lock-implementeringer er et højniveau alternativ til synchronized-blokke, og Condition-interface-implementeringer er et alternativ til notify()/wait()-metoderne. Begge disse interfaces er en del af pakken java.util.concurrent.locks.
Virkelige eksempler
Forestil dig, at du administrerer en kø til tilmelding til et arrangement. For at forhindre overløb og sikre korrekt sædetildeling, skal du bruge blokeringsmekanismer og betingelser for at holde strømmen af nye tilmeldinger ventende, indtil en ledig plads bliver tilgængelig.
ReentrantLock-klassen
ReentrantLock klassen fra java.util.concurrent.locks pakken er en implementering af Lock interfacet. Den giver funktionalitet til eksplicit håndtering af låse.
De vigtigste metoder i ReentrantLock:
lock(): Optager en lås;unlock(): Frigiver låsen;tryLock(): Forsøger at optage låsen og returnerer true, hvis det lykkes;tryLock(long timeout, TimeUnit unit): Forsøger at optage låsen i den angivne tid;newCondition(): Opretter en betingelse for den aktuelleLock.
Main.java
12345678910111213141516171819202122232425262728293031package com.example; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Main { // Creating a ReentrantLock object private final Lock lock = new ReentrantLock(); private int count = 0; // Method to increment the `count` variable public void increment() { lock.lock(); // Acquiring the `lock` try { count++; System.out.println("Count incremented to: " + count); } finally { lock.unlock(); // Releasing the `lock` } } public static void main(String[] args) { Main example = new Main(); // Runnable task to call the increment method Runnable task = example::increment; // Starting multiple threads to execute the task for (int i = 0; i < 5; i++) { new Thread(task).start(); } } }
Som du kan se, anvender vi låsning med increment() i metoden Lock. Når en tråd går ind i metoden, optager den låsen med lock.lock(), udfører derefter koden, og i finally-blokken frigiver vi låsen med lock.unlock(), så andre tråde kan få adgang.
Vi frigiver låsen i finally-blokken af en grund, nemlig at denne blok næsten altid bliver udført, selv ved undtagelser, undtagen når programmet afsluttes.
Condition-interface
Vi kan kun oprette et Condition-objekt med binding til en specifik Lock-implementering. Af denne grund vil Condition-metoderne kun påvirke låsningen af netop denne Lock-implementering.
Main.java
12private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition();
De vigtigste metoder for Condition:
await(): Venter på et signal fra en anden tråd;signal(): Låser én tråd op, som venter på en betingelse;signalAll(): Låser alle tråde op, der venter på betingelsen.
Main.java
12345678910111213141516private final ReentrantLock lock = new ReentrantLock(); private final Condition condition = lock.newCondition(); private boolean ready = false; public void waitForCondition() throws InterruptedException { lock.lock(); // Acquire the `lock` try { while (!ready) { // Check if the condition is not met System.out.println("Waiting..."); // Print a waiting message condition.await(); // Wait for the condition to be signaled } System.out.println("Condition met!"); // Print a message when the condition is met } finally { lock.unlock(); // Release the `lock` } }
Metoden waitForCondition() blokerer tråden, indtil variablen ready bliver true, hvilket signalerer, at betingelsen er opfyldt. Når betingelsen er opfyldt, fortsætter tråden med at køre og viser beskeden “Condition met!”
Når metoden await() kaldes, bliver tråden pauset og frigiver også låsen, den har optaget. Når tråden vågner op, skal den optage låsen igen, og først derefter vil den begynde at udføre!
Kodeeksempel
Lad os nu se et eksempel på brug af ReentrantLock og Condition til at håndtere tilmelding til et arrangement:
Et kort klip fra videoen
Låsning med ReentrantLock: Metoden register() optager låsen med lock.lock() for at forhindre, at flere tråde udfører koden samtidigt.
Betingelse med Condition: Hvis der ikke er ledige pladser, kalder tråden spaceAvailable.await() for at vente, indtil der er plads tilgængelig.
Frigiv lås: Når en tråd har frigivet plads ved at bruge metoden cancel(), kalder den spaceAvailable.signalAll() for at underrette alle ventende tråde.
Undtagelseshåndtering: Brug af try-finally blokke sikrer, at låsen frigives, selv hvis en undtagelse opstår.
Brugen af Lock og Condition i Java muliggør mere fleksibel kontrol over tråde og synkronisering end den traditionelle synchronized-mekanisme. Dette er især nyttigt i komplekse scenarier, hvor mere præcis kontrol over tråde og ventebetingelser er påkrævet.
Tak for dine kommentarer!