Синхронизация и состояния потоков
Дайте определение понятию «синхронизация».
Синхронизация в программировании — это механизм, обеспечивающий правильное выполнение потоков при одновременном доступе к общим ресурсам. Она предотвращает состояние гонки и обеспечивает согласованность данных, синхронизируя доступ к критическим секциям кода.
Пример:public class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
В этом примере методы increment и getCount синхронизированы, что гарантирует корректный доступ к переменной count из нескольких потоков.
Какие существуют способы синхронизации в Java?
Способы синхронизации в Java:-
Ключевое слово
synchronized:-
Синхронизация методов:
public synchronized void method() { // код } -
Синхронизация блоков:
public void method() { synchronized (this) { // код } }
-
-
Объект
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(); } }
-
-
Классы из
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(); } }
-
-
Атомарные переменные:
-
Классы из
java.util.concurrent.atomic, обеспечивающие атомарные операции. -
Пример:
import java.util.concurrent.atomic.AtomicInteger; private final AtomicInteger count = new AtomicInteger(0); public void increment() { count.incrementAndGet(); }
-
-
Синхронизированные коллекции:
-
Коллекции из
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:-
NEW (новый):
-
Поток создан, но ещё не запущен.
-
Пример:
Thread thread = new Thread();
-
-
RUNNABLE (работающий):
-
Поток запущен и готов к выполнению.
-
Пример:
thread.start();
-
-
BLOCKED (заблокированный):
-
Поток ожидает освобождения монитора, чтобы войти в синхронизированный блок/метод.
-
Пример:
synchronized (obj) { /* код */ }
-
-
WAITING (ожидание):
-
Поток ожидает другого потока для выполнения определённого действия (например, вызова
notify()илиnotifyAll()). -
Пример:
obj.wait();
-
-
TIMED_WAITING (ожидание с таймаутом):
-
Поток ожидает определённый период времени.
-
Пример:
Thread.sleep(1000);илиobj.wait(1000);
-
-
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 захватывает ресурс A и ожидает ресурс B.
-
Поток 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 вызываются одновременно в разных потоках, может произойти взаимная блокировка.