Java. Чому локи потрібно тримати якомога менший час?

Збільшення пропускної здатності. Коротший час блокувань може збільшити загальну пропускну здатність системи, оскільки більше потоків може отримати доступ до синхронізованих секцій протягом певного часу.

Реагування на “зовнішні“ події. Коли потоки не чекають довго на доступ до ресурсу через короткі блокування, вони можуть швидше реагувати на зовнішні події. Це може бути критично важливо для систем реального часу або для тих, які мають високі вимоги до часу відгуку(веб-сервери — обробка запитів, бази даних).

Зменшення ризику взаємоблокування. Тримання кількох блокувань одночасно або протягом тривалого часу збільшує ризик взаємоблокувань. Короткі інтервали блокувань мінімізують часове “вікно“, протягом якого інший потік може спробувати отримати блокування в іншому порядку та викликати взаємоблокування.

Прогнозованість та легший дебаг. Системи з довгою тривалістю блокування можуть проявляти непередбачувану поведінку, оскільки важко визначити послідовність операцій у різних потоках(тримання локу “розсинхронізовує/віддаляє“ роботу декількох потоків один від одного). Зберігаючи короткий час блокувань, можна зробити поведінку системи більш прогнозованою та легше її проаналізувати.

Інтерфейс: У додатках з графічним інтерфейсом, довгі блокування можуть призвести до "зависання"(пост про це) або затримок відгуку, що може погіршити враження від користування додатком.


public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(5_000);

        final Object lock = new Object();
        MyThread t1 = new MyThread("My Thread 1", lock);
        MyThread t2 = new MyThread("My Thread 2", lock);

        Thread.sleep(1000);
        System.out.println(t2.getState());
        System.out.println(t1.getState());
    }
}

class MyThread extends Thread {
    private final Object lock;

    public MyThread(String name, Object lock) {
        setName(name);
        this.lock = lock;
        start();
    }

    @Override
    public void run() {
        synchronized (lock) {
            System.out.println("Hello from thread " + getName());
            while (true);
            // довгі обрахунки
        }
        // інша бізнес логіка яку необхідно виконати
    }
}
Результат запуску програми в консолі
Java process profiling. VisualVM

В профайлері бачимо наших два потоки — My Thread 1 і My Thread 2.
Оскільки перший потік запускається першим, він займає лок, другий потік, чекає на цьому лоці нескінченний час і переходить в заблокований стан. Через блокування, код потоку не буде виконано процесором — не буде використано процесорного часу, навідміну від першого потоку.

Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Oleksandr Klymenko
Oleksandr Klymenko@overpathz

Java Software Engineer

4.6KПрочитань
1Автори
71Читачі
На Друкарні з 19 квітня

Більше від автора

  • Secure networking. Deep Dive

    Глибоке занурення в протоколи TLS/SSL та інфраструктуру відкритих ключів (PKI). Основні поняття, процес встановлення захищеного з'єднання, роль сертифікатів та ланцюжка довіри

    Теми цього довгочиту:

    Security
  • Поширені помилки у дизайні REST API

    У довгочиті розглядаються поширені помилки при проектуванні REST API та способи їх уникнення: версіонування, використання DTO, підхід CQRS, робота з мікросервісами, та інші практики для підвищення продуктивності, безпеки й зручності API

    Теми цього довгочиту:

    Java
  • Java. Короткий огляд еволюції багатопотоковості

    У перших версіях Java багатопоточність реалізовувалася за допомогою класу Thread, який дозволяв створювати нові потоки. Проте ця модель мала багато недоліків:

    Теми цього довгочиту:

    Java

Вам також сподобається

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Вам також сподобається