Назад к вопросам
Middle
68
questionbank

Какие способы синхронизации в Java вы знаете?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

В Java существует несколько основных механизмов синхронизации для управления доступом к общим ресурсам из разных потоков:

  • synchronized ключевое слово: Может применяться к методам и блокам кода. Обеспечивает атомарность и видимость.

    // Синхронизация метода
    public synchronized void increment() {
        count++;
    }
    
    // Синхронизация блока кода
    public void updateList() {
        synchronized (myList) {
            myList.add(newItem);
        }
    }
    
  • Явные блокировки (java.util.concurrent.locks)

    • ReentrantLock: Реентерабельная, позволяет выполнять блокировку несколько раз одним потоком.

      import java.util.concurrent.locks.ReentrantLock;
      
      private final ReentrantLock lock = new ReentrantLock();
      
      public void performTask() {
          lock.lock();
          try {
              // Критическая секция
          } finally {
              lock.unlock();
          }
      }
      
    • ReentrantReadWriteLock: Разделяет блокировку на чтение и запись, позволяя нескольким потокам читать одновременно, но только одному записывать.

      import java.util.concurrent.locks.ReentrantReadWriteLock;
      
      private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
      private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
      private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
      
      public void readData() {
          readLock.lock();
          try {
              // Чтение данных
          } finally {
              readLock.unlock();
          }
      }
      
      public void writeData() {
          writeLock.lock();
          try {
              // Запись данных
          } finally {
              writeLock.unlock();
          }
      }
      
  • Семафоры (Semaphore): Ограничивают количество потоков, которые могут одновременно получить доступ к определенному ресурсу.

    import java.util.concurrent.Semaphore;
    
    private final Semaphore semaphore = new Semaphore(5); // Разрешаем 5 потокам
    
    public void accessResource() throws InterruptedException {
        semaphore.acquire(); // Запрашиваем разрешение
        try {
            // Работа с ресурсом
        } finally {
            semaphore.release(); // Освобождаем разрешение
        }
    }
    
  • Мьютексы (Mutex): Хотя в Java нет отдельного класса Mutex, ReentrantLock часто используется как аналог мьютекса (блокировка только одним потоком).

  • Объекты для синхронизации потоков (java.util.concurrent)

    • CountDownLatch: Позволяет одному или нескольким потокам ждать, пока определенное количество операций не завершится.

      import java.util.concurrent.CountDownLatch;
      
      private final CountDownLatch latch = new CountDownLatch(3); // Ждем 3 завершения
      
      // Потоки выполняют задачи и уменьшают счетчик: latch.countDown();
      // Поток-ожидатель: latch.await();
      
    • CyclicBarrier: Позволяет группе потоков ждать друг друга в определенной точке перед тем, как продолжить выполнение.

      import java.util.concurrent.CyclicBarrier;
      
      private final CyclicBarrier barrier = new CyclicBarrier(4); // Барьер для 4 потоков
      
      // Потоки выполняют задачи и достигают барьера: barrier.await();
      
    • Exchanger: Позволяет двум потокам обмениваться объектами в точке синхронизации.

      import java.util.concurrent.Exchanger;
      
      private final Exchanger<String> exchanger = new Exchanger<>();
      
      // В одном потоке: String received = exchanger.exchange("Отправляю");
      // В другом потоке: String received = exchanger.exchange("Получаю");
      
  • Синхронизированные коллекции (Collections.synchronized...)

    • Оборачивают обычные коллекции, делая их потокобезопасными.
    • Пример: Collections.synchronizedList(new ArrayList<>())
  • Потокобезопасные коллекции (java.util.concurrent)

    • Предоставляют более высокопроизводительные и гибкие альтернативы синхронизированным коллекциям.
    • Примеры: ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue (например, ArrayBlockingQueue, LinkedBlockingQueue).

Выбор метода синхронизации зависит от конкретной задачи и требований к производительности и атомарности.