Перейти к содержимому
шпаргалка.
Esc
навигацияоткрыть⌘Jпредпросмотр
На этой странице

Синхронизация и состояния потоков

Все темы Java Developer

Дайте определение понятию «синхронизация».

Синхронизация в программировании — это механизм, обеспечивающий правильное выполнение потоков при одновременном доступе к общим ресурсам. Она предотвращает состояние гонки и обеспечивает согласованность данных, синхронизируя доступ к критическим секциям кода.

Пример:
public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

В этом примере методы increment и getCount синхронизированы, что гарантирует корректный доступ к переменной count из нескольких потоков.


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

Способы синхронизации в Java:
  1. Ключевое слово synchronized :
    • Синхронизация методов:

      public synchronized void method() {
          // код
      }
    • Синхронизация блоков:

      public void method() {
          synchronized (this) {
              // код
          }
      }
  2. Объект Lock из java.util.concurrent.locks :
    • Реализация блокировок с расширенными возможностями.

    • Пример:

      import java.util.concurrent.locks.Lock;
      import java.util.concurrent.locks.ReentrantLock;
      
      private final Lock lock = new ReentrantLock();
      
      public void method() {
          lock.lock();
          try {
              // код
          } finally {
              lock.unlock();
          }
      }
  3. Классы из java.util.concurrent :
    • ReentrantLock, ReadWriteLock, StampedLock для расширенной синхронизации.

    • Пример использования ReadWriteLock:

      import java.util.concurrent.locks.ReentrantReadWriteLock;
      import java.util.concurrent.locks.ReadWriteLock;
      
      private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
      
      public void readMethod() {
          rwLock.readLock().lock();
          try {
              // код для чтения
          } finally {
              rwLock.readLock().unlock();
          }
      }
      
      public void writeMethod() {
          rwLock.writeLock().lock();
          try {
              // код для записи
          } finally {
              rwLock.writeLock().unlock();
          }
      }
  4. Атомарные переменные:
    • Классы из java.util.concurrent.atomic, обеспечивающие атомарные операции.

    • Пример:

      import java.util.concurrent.atomic.AtomicInteger;
      
      private final AtomicInteger count = new AtomicInteger(0);
      
      public void increment() {
          count.incrementAndGet();
      }
  5. Синхронизированные коллекции:
    • Коллекции из java.util.Collections.synchronizedList, synchronizedMap.

    • Пример:

      import java.util.Collections;
      import java.util.List;
      import java.util.ArrayList;
      
      List<String> syncList = Collections.synchronizedList(new ArrayList<>());

В каких состояниях может находиться поток?

Состояния потока в Java:
  1. NEW (новый):
    • Поток создан, но ещё не запущен.

    • Пример: Thread thread = new Thread();

  2. RUNNABLE (работающий):
    • Поток запущен и готов к выполнению.

    • Пример: thread.start();

  3. BLOCKED (заблокированный):
    • Поток ожидает освобождения монитора, чтобы войти в синхронизированный блок/метод.

    • Пример: synchronized (obj) { /* код */ }

  4. WAITING (ожидание):
    • Поток ожидает другого потока для выполнения определённого действия (например, вызова notify() или notifyAll()).

    • Пример: obj.wait();

  5. TIMED_WAITING (ожидание с таймаутом):
    • Поток ожидает определённый период времени.

    • Пример: Thread.sleep(1000); или obj.wait(1000);

  6. TERMINATED (завершённый):
    • Поток завершил выполнение.

    • Пример: Метод run() завершил выполнение.


Как работают методы wait() и notify()/notifyAll()?

Методы wait() , notify() , notifyA :
  • wait() :
    • wait() освобождает монитор данного объекта и ожидает уведомления, прерывания или ложного пробуждения; вариант с таймаутом также ограничивает ожидание. Перед возвратом поток снова захватывает монитор. Условие проверяют в цикле while, а не считают само пробуждение доказательством готовности.

    • Вызывается на объекте внутри синхронизированного блока.

    • Пример:

      synchronized (obj) {
          obj.wait();
      }
  • notify() :
    • Пробуждает один из потоков, ожидающих на этом объекте.

    • Поток переходит из состояния WAITING в состояние BLOCKED.

    • Пример:

      synchronized (obj) {
          obj.notify();
      }
  • notifyAll() :
    • Пробуждает все потоки, ожидающие на этом объекте.

    • Все пробужденные потоки переходят в состояние BLOCKED.

    • Пример:

      synchronized (obj) {
          obj.notifyAll();
      }

Что такое deadlock?

Deadlock — это ситуация, когда два или более потоков навсегда блокируют друг друга, ожидая освобождения ресурсов, захваченных другими потоками.

Ситуация:

  1. Поток 1 захватывает ресурс A и ожидает ресурс B.

  2. Поток 2 захватывает ресурс B и ожидает ресурс A.

Оба потока блокируют друг друга, и выполнение программы останавливается.

Пример:

public class DeadlockExample {
    private final Object resourceA = new Object();
    private final Object resourceB = new Object();

    public void method1() {
        synchronized (resourceA) {
            synchronized (resourceB) {
                // код
            }
        }
    }

    public void method2() {
        synchronized (resourceB) {
            synchronized (resourceA) {
                // код
            }
        }
    }
}

В этом примере, если method1 и method2 вызываются одновременно в разных потоках, может произойти взаимная блокировка.

Эта страница была полезной?