23:45
Урок 26: Высокоуровневые примитивы синхронизации

Курс по программированию на Java

Урок 26: Высокоуровневые примитивы синхронизации

Высокоуровневые примитивы синхронизации в Java, такие как ReentrantLock, Semaphore и CountDownLatch, предоставляют дополнительные возможности для управления потоками и синхронизации. Эти примитивы позволяют более гибко и эффективно решать задачи синхронизации по сравнению с традиционными средствами, такими как synchronized.

ReentrantLock

ReentrantLock — это замок, который предоставляет все возможности synchronized, но с дополнительными функциями, такими как возможность попытки захвата замка, возможность прерывания захвата и возможность тайм-аутов.

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
 private final Lock lock = new ReentrantLock();
 private int count = 0;

 public void increment() {
 lock.lock();
 try {
 count++;
 } finally {
 lock.unlock();
 }
 }

 public int getCount() {
 return count;
 }

 public static void main(String[] args) {
 ReentrantLockExample example = new ReentrantLockExample();
 
 Thread t1 = new Thread(() -> {
 for (int i = 0; i < 1000; i++) {
 example.increment();
 }
 });
 
 Thread t2 = new Thread(() -> {
 for (int i = 0; i < 1000; i++) {
 example.increment();
 }
 });
 
 t1.start();
 t2.start();
 
 try {
 t1.join();
 t2.join();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 
 System.out.println("Count: " + example.getCount());
 }
}

Результат выполнения

Count: 2000

Semaphore

Semaphore ограничивает количество потоков, которые могут одновременно получить доступ к ресурсу. Это полезно для управления доступом к ресурсам, которые имеют ограниченное количество экземпляров, например, подключения к базе данных.

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
 private final Semaphore semaphore = new Semaphore(1);

 public void accessResource() {
 try {
 semaphore.acquire();
 System.out.println("Доступ к ресурсу получен");
 Thread.sleep(1000); // Имитация работы с ресурсом
 } catch (InterruptedException e) {
 e.printStackTrace();
 } finally {
 semaphore.release();
 System.out.println("Ресурс освобожден");
 }
 }

 public static void main(String[] args) {
 SemaphoreExample example = new SemaphoreExample();
 
 Thread t1 = new Thread(example::accessResource);
 Thread t2 = new Thread(example::accessResource);
 
 t1.start();
 t2.start();
 }
}

Результат выполнения

Доступ к ресурсу получен
Ресурс освобожден
Доступ к ресурсу получен
Ресурс освобожден

Упражнения

Упражнение 1: Использование ReentrantLock

Напишите программу, которая создает счетчик и два потока, увеличивающие значение счетчика с использованием ReentrantLock для синхронизации доступа.

Решение:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Counter {
 private final Lock lock = new ReentrantLock();
 private int count = 0;

 public void increment() {
 lock.lock();
 try {
 count++;
 } finally {
 lock.unlock();
 }
 }

 public int getCount() {
 return count;
 }

 public static void main(String[] args) {
 Counter counter = new Counter();
 
 Thread t1 = new Thread(() -> {
 for (int i = 0; i < 1000; i++) {
 counter.increment();
 }
 });
 
 Thread t2 = new Thread(() -> {
 for (int i = 0; i < 1000; i++) {
 counter.increment();
 }
 });
 
 t1.start();
 t2.start();
 
 try {
 t1.join();
 t2.join();
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 
 System.out.println("Count: " + counter.getCount());
 }
}

Объяснение: Программа создает объект Counter и два потока, которые одновременно увеличивают значение счетчика. Для синхронизации используется ReentrantLock, чтобы предотвратить одновременное изменение значения.

Упражнение 2: Использование Semaphore

Напишите программу, которая ограничивает доступ к ресурсу тремя потоками одновременно, используя Semaphore.

Решение:

import java.util.concurrent.Semaphore;

public class ResourceAccess {
 private final Semaphore semaphore = new Semaphore(3);

 public void accessResource() {
 try {
 semaphore.acquire();
 System.out.println("Доступ к ресурсу получен " + Thread.currentThread().getName());
 Thread.sleep(1000); // Имитация работы с ресурсом
 } catch (InterruptedException e) {
 e.printStackTrace();
 } finally {
 semaphore.release();
 System.out.println("Ресурс освобожден " + Thread.currentThread().getName());
 }
 }

 public static void main(String[] args) {
 ResourceAccess resourceAccess = new ResourceAccess();
 
 for (int i = 0; i < 5; i++) {
 Thread thread = new Thread(resourceAccess::accessResource, "Поток-" + i);
 thread.start();
 }
 }
}

Объяснение: Программа создает объект ResourceAccess и пять потоков, которые пытаются получить доступ к ресурсу. Semaphore позволяет одновременно получить доступ только трем потокам.

Категория: Java | Просмотров: 110 | Добавил: Admin | Рейтинг: 0.0/0
Всего комментариев: 0
Имя *:
Email *:
Код *: