Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Leer Lock en Condition | High-Level Synchronisatiemechanismen
Multithreading in Java

bookLock en Condition

In Java is standaard synchronisatie gebaseerd op het sleutelwoord synchronized en ingebouwde monitorobjecten. In sommige gevallen is synchronized echter niet toereikend, vooral wanneer meer flexibiliteit in threadbeheer vereist is.

Algemene Beschrijving

De Lock-interface en de Condition-interface, geïntroduceerd in het pakket java.util.concurrent.locks, bieden geavanceerde mogelijkheden voor threadbeheer.

In deze afbeelding is te zien dat de eerste thread de lock vastlegt met de lock()-methode, en op dat moment kan een andere thread dezelfde lock niet verkrijgen. Zodra alle code binnen de lock is uitgevoerd, wordt de unlock()-methode aangeroepen en wordt de lock vrijgegeven. Pas daarna kan de tweede thread de lock verkrijgen.

Verschil

Het verschil tussen deze twee interfaces is dat de implementaties van Lock een hoog-niveau alternatief zijn voor het synchronized block, en de implementaties van de Condition-interface een alternatief vormen voor de notify()/wait()-methoden. Beide interfaces maken deel uit van het pakket java.util.concurrent.locks.

Praktijkvoorbeelden

Stel je beheert een wachtrij voor registratie voor een evenement. Om overloop te voorkomen en een correcte toewijzing van zitplaatsen te waarborgen, is het noodzakelijk om blokkeringsmechanismen en condities te gebruiken zodat nieuwe registraties wachten totdat er een vrije plaats beschikbaar is.

ReentrantLock-klasse

De klasse ReentrantLock uit het pakket java.util.concurrent.locks is een implementatie van de interface Lock. Deze biedt functionaliteit voor het expliciet beheren van locks.

De belangrijkste methoden van ReentrantLock:

  • lock(): Neemt een lock in beslag;
  • unlock(): Geeft de lock vrij;
  • tryLock(): Probeert de lock te verkrijgen en retourneert true als dit lukt;
  • tryLock(long timeout, TimeUnit unit): Probeert de lock te verkrijgen gedurende de opgegeven tijd;
  • newCondition(): Maakt een conditie aan voor de huidige Lock.
Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031
package 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(); } } }

Zoals te zien is, gebruiken we in de increment()-methode vergrendeling met Lock. Wanneer een thread de methode binnenkomt, verkrijgt deze de lock via lock.lock(), voert vervolgens de code uit en in het finally-blok wordt de lock vrijgegeven met lock.unlock(), zodat andere threads toegang kunnen krijgen.

We geven de lock vrij in het finally-blok met een reden: dit blok wordt vrijwel altijd uitgevoerd, zelfs bij exceptions, behalve wanneer het programma wordt beëindigd.

Condition-interface

Een Condition kan alleen worden aangemaakt in combinatie met een specifieke Lock-implementatie. Om deze reden zullen de methoden van Condition alleen invloed hebben op de vergrendeling van die specifieke Lock-implementatie.

Main.java

Main.java

copy
12
private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition();

De belangrijkste methoden van Condition:

  • await(): Wacht op een signaal van een andere thread;
  • signal(): Deblokkeert één thread die wacht op een conditie;
  • signalAll(): Deblokkeert alle threads die op de conditie wachten.
Main.java

Main.java

copy
12345678910111213141516
private 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` } }

De methode waitForCondition() blokkeert de thread totdat de variabele ready true wordt, wat aangeeft dat aan de voorwaarde is voldaan. Zodra aan de voorwaarde is voldaan, gaat de thread verder en wordt het bericht “Condition met!” weergegeven.

Note
Opmerking

Wanneer de methode await() wordt aangeroepen, wordt de thread gepauzeerd en geeft het ook de lock vrij die het heeft verkregen. Wanneer de thread ontwaakt, moet het de lock opnieuw verkrijgen en pas dan zal het beginnen met uitvoeren!

Codevoorbeeld

Laten we nu een voorbeeld bekijken van het gebruik van ReentrantLock en Condition om de registratie voor een evenement te beheren:

Een korte clip uit de video

Vergrendelen met ReentrantLock: De register()-methode verkrijgt de lock met lock.lock() om te voorkomen dat meerdere threads tegelijkertijd code uitvoeren.

Condition met Condition: Als er geen beschikbare plaatsen zijn, roept de thread spaceAvailable.await() aan om te wachten tot er ruimte beschikbaar is.

Vrijgeven van lock: Wanneer een thread ruimte heeft vrijgegeven via de cancel()-methode, roept deze spaceAvailable.signalAll() aan om alle wachtende threads te informeren.

Foutafhandeling: Het gebruik van try-finally-blokken zorgt ervoor dat de lock wordt vrijgegeven, zelfs als er een exceptie optreedt.

Note
Opmerking

Het gebruik van Lock en Condition in Java biedt flexibelere controle over threads en synchronisatie dan het traditionele synchronized-mechanisme. Dit is vooral nuttig in complexe scenario's waarin nauwkeurige controle over threads en wachtcondities vereist is.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 3. Hoofdstuk 1

Vraag AI

expand

Vraag AI

ChatGPT

Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.

Suggested prompts:

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

bookLock en Condition

Veeg om het menu te tonen

In Java is standaard synchronisatie gebaseerd op het sleutelwoord synchronized en ingebouwde monitorobjecten. In sommige gevallen is synchronized echter niet toereikend, vooral wanneer meer flexibiliteit in threadbeheer vereist is.

Algemene Beschrijving

De Lock-interface en de Condition-interface, geïntroduceerd in het pakket java.util.concurrent.locks, bieden geavanceerde mogelijkheden voor threadbeheer.

In deze afbeelding is te zien dat de eerste thread de lock vastlegt met de lock()-methode, en op dat moment kan een andere thread dezelfde lock niet verkrijgen. Zodra alle code binnen de lock is uitgevoerd, wordt de unlock()-methode aangeroepen en wordt de lock vrijgegeven. Pas daarna kan de tweede thread de lock verkrijgen.

Verschil

Het verschil tussen deze twee interfaces is dat de implementaties van Lock een hoog-niveau alternatief zijn voor het synchronized block, en de implementaties van de Condition-interface een alternatief vormen voor de notify()/wait()-methoden. Beide interfaces maken deel uit van het pakket java.util.concurrent.locks.

Praktijkvoorbeelden

Stel je beheert een wachtrij voor registratie voor een evenement. Om overloop te voorkomen en een correcte toewijzing van zitplaatsen te waarborgen, is het noodzakelijk om blokkeringsmechanismen en condities te gebruiken zodat nieuwe registraties wachten totdat er een vrije plaats beschikbaar is.

ReentrantLock-klasse

De klasse ReentrantLock uit het pakket java.util.concurrent.locks is een implementatie van de interface Lock. Deze biedt functionaliteit voor het expliciet beheren van locks.

De belangrijkste methoden van ReentrantLock:

  • lock(): Neemt een lock in beslag;
  • unlock(): Geeft de lock vrij;
  • tryLock(): Probeert de lock te verkrijgen en retourneert true als dit lukt;
  • tryLock(long timeout, TimeUnit unit): Probeert de lock te verkrijgen gedurende de opgegeven tijd;
  • newCondition(): Maakt een conditie aan voor de huidige Lock.
Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031
package 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(); } } }

Zoals te zien is, gebruiken we in de increment()-methode vergrendeling met Lock. Wanneer een thread de methode binnenkomt, verkrijgt deze de lock via lock.lock(), voert vervolgens de code uit en in het finally-blok wordt de lock vrijgegeven met lock.unlock(), zodat andere threads toegang kunnen krijgen.

We geven de lock vrij in het finally-blok met een reden: dit blok wordt vrijwel altijd uitgevoerd, zelfs bij exceptions, behalve wanneer het programma wordt beëindigd.

Condition-interface

Een Condition kan alleen worden aangemaakt in combinatie met een specifieke Lock-implementatie. Om deze reden zullen de methoden van Condition alleen invloed hebben op de vergrendeling van die specifieke Lock-implementatie.

Main.java

Main.java

copy
12
private final Lock lock = new ReentrantLock(); private final Condition condition = lock.newCondition();

De belangrijkste methoden van Condition:

  • await(): Wacht op een signaal van een andere thread;
  • signal(): Deblokkeert één thread die wacht op een conditie;
  • signalAll(): Deblokkeert alle threads die op de conditie wachten.
Main.java

Main.java

copy
12345678910111213141516
private 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` } }

De methode waitForCondition() blokkeert de thread totdat de variabele ready true wordt, wat aangeeft dat aan de voorwaarde is voldaan. Zodra aan de voorwaarde is voldaan, gaat de thread verder en wordt het bericht “Condition met!” weergegeven.

Note
Opmerking

Wanneer de methode await() wordt aangeroepen, wordt de thread gepauzeerd en geeft het ook de lock vrij die het heeft verkregen. Wanneer de thread ontwaakt, moet het de lock opnieuw verkrijgen en pas dan zal het beginnen met uitvoeren!

Codevoorbeeld

Laten we nu een voorbeeld bekijken van het gebruik van ReentrantLock en Condition om de registratie voor een evenement te beheren:

Een korte clip uit de video

Vergrendelen met ReentrantLock: De register()-methode verkrijgt de lock met lock.lock() om te voorkomen dat meerdere threads tegelijkertijd code uitvoeren.

Condition met Condition: Als er geen beschikbare plaatsen zijn, roept de thread spaceAvailable.await() aan om te wachten tot er ruimte beschikbaar is.

Vrijgeven van lock: Wanneer een thread ruimte heeft vrijgegeven via de cancel()-methode, roept deze spaceAvailable.signalAll() aan om alle wachtende threads te informeren.

Foutafhandeling: Het gebruik van try-finally-blokken zorgt ervoor dat de lock wordt vrijgegeven, zelfs als er een exceptie optreedt.

Note
Opmerking

Het gebruik van Lock en Condition in Java biedt flexibelere controle over threads en synchronisatie dan het traditionele synchronized-mechanisme. Dit is vooral nuttig in complexe scenario's waarin nauwkeurige controle over threads en wachtcondities vereist is.

Was alles duidelijk?

Hoe kunnen we het verbeteren?

Bedankt voor je feedback!

Sectie 3. Hoofdstuk 1
some-alt