← Назад к вопросам

В чем разница между методом lock() и async()?

1.7 Middle🔥 81 комментариев
#Многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между методом lock() и async()

Методы lock() и async() относятся к различным парадигмам работы с параллелизмом и асинхронностью в Java. Это часто вызывает путаницу, особенно для разработчиков, переходящих из других языков или только начинающих работать с конкурентностью. Давайте разберемся в деталях.

Важное уточнение

В стандартной Java API нет встроенного метода async(). Однако есть несколько интерпретаций:

  1. lock() — из пакета java.util.concurrent.locks
  2. async() — может означать асинхронное программирование в целом (CompletableFuture, reactive frameworks)
  3. async() — если имеется в виду какой-то конкретный framework (Spring, RxJava, Project Reactor)

Разберу основные парадигмы параллелизма в Java.

Метод lock() — синхронизация потоков

Метод lock() является частью интерфейса Lock в пакете java.util.concurrent.locks. Это механизм для синхронизации доступа к общим ресурсам в многопоточной среде:

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

public class Counter {
    private int count = 0;
    private Lock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock(); // Получить блокировку
        try {
            count++; // Критическая секция
        } finally {
            lock.unlock(); // Освободить блокировку
        }
    }
    
    public int getCount() {
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
}

Характеристики lock():

  • Синхронная блокировка — поток ждет, пока ресурс освободится
  • Явное управление — нужно вызвать lock() и unlock()
  • Гибкость — может быть использована с различными условиями (Condition)
  • Более мощная, чем synchronized — поддерживает tryLock(), можно установить timeout
  • Блокирует поток — поток ждет в активном состоянии

Асинхронность — альтернатива блокировкам

Асинхронное программирование позволяет работать с результатами, которые придут позже, без блокировки потока:

Пример 1: CompletableFuture (встроенный в Java 8+)

import java.util.concurrent.CompletableFuture;

public class AsyncExample {
    
    // Имитация асинхронной операции
    public CompletableFuture<String> fetchDataAsync() {
        return CompletableFuture.supplyAsync(() -> {
            // Длительная операция в отдельном потоке
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            return "Данные получены";
        });
    }
    
    public void example() {
        // Неблокирующий вызов
        fetchDataAsync()
            .thenAccept(result -> System.out.println(result))
            .thenRun(() -> System.out.println("Готово"));
        
        // Поток продолжает работу, не ожидая результата
        System.out.println("Запрос отправлен");
    }
}

Пример 2: Reactive Programming (RxJava, Project Reactor)

import io.reactivex.rxjava3.core.Observable;

public class ReactiveExample {
    
    public Observable<String> fetchDataReactive() {
        return Observable.create(emitter -> {
            new Thread(() -> {
                try {
                    Thread.sleep(2000);
                    emitter.onNext("Данные получены");
                    emitter.onComplete();
                } catch (Exception e) {
                    emitter.onError(e);
                }
            }).start();
        });
    }
    
    public void example() {
        fetchDataReactive()
            .map(String::toUpperCase)
            .subscribe(
                result -> System.out.println(result),
                error -> System.err.println(error),
                () -> System.out.println("Готово")
            );
    }
}

Сравнительная таблица

Аспектlock()async() / Асинхронность
ПарадигмаСинхронная блокировкаАсинхронность без блокировки
Блокировка потокаДа, поток ждетНет, поток свободен
СложностьПроще понять, но может привести к deadlockСложнее, но более эффективно
ПроизводительностьПри малом количестве потоков хорошоОтлично при высокой нагрузке
Callback hellНе применимоВозможен без правильной структуры
ИспользованиеСинхронизация общих ресурсовAPI вызовы, I/O операции, обработка событий
Thread poolТребует много потоковЭффективен с небольшим количеством потоков

Пример конкурентного доступа

С использованием lock():

public class ThreadSafeCounter {
    private int value = 0;
    private Lock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            value++;
            Thread.sleep(100); // Имитация работы
        } finally {
            lock.unlock();
        }
    }
}

// Использование
ThreadSafeCounter counter = new ThreadSafeCounter();
for (int i = 0; i < 10; i++) {
    new Thread(counter::increment).start();
}

С использованием synchronized (альтернатива lock):

public class SynchronizedCounter {
    private int value = 0;
    
    public synchronized void increment() {
        value++;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

Когда использовать что?

Используй lock() когда:

  • Нужна синхронизация общих ресурсов между потоками
  • Требуется явное управление блокировкой
  • Нужны условные переменные (Condition)
  • Нужна возможность прерывания (interruptible lock)

Используй асинхронность когда:

  • Много I/O операций (HTTP запросы, БД запросы)
  • Нужна высокая пропускная способность
  • Работаешь с микросервисной архитектурой
  • Нужна реактивная обработка потоков данных
  • Строишь event-driven приложение

Современный подход в Java

В современной Java предпочтительнее использовать асинхронные подходы (CompletableFuture, Project Reactor, Quarkus с virtual threads). Это более эффективно и лучше масштабируется. Но понимание lock() остается важным для интервью и для работы с legacy кодом.

В чем разница между методом lock() и async()? | PrepBro