Syncхронізація в Java

Що таке Syncхронізація в Java?

In Java, синхронізація означає можливість контролювати доступ кількох потоків до будь-якого спільного ресурсу. Це ідеальний варіант, коли ми хочемо дозволити лише одному потоку отримати доступ до спільного ресурсу.

Такий підхід до виконання зазвичай називають «асинхронним» програмуванням. На цих процесорах також є потоки, які є легкими процесами, які можуть виконувати інструкції одночасно.

Види Syncхронізація

Існує два типи методів синхронізації Java:

1) Синхронізація процесів

2) Синхронізація потоків.

Вивчаємо Thread і Синхронізація процесів детально.

Синхронізація процесів: Він керує синхронізацією між програмами. Наприклад, такі програми, як `Microsoft Word` і `Acrobat reader` запускаються як окремі процеси.

Синхронізація потоків: Одночасне виконання критичного ресурсу двома або більше потоками називається потоком Syncхронізація. Ви можете бути згруповані до взаємовиключних і міжпотокових комунікацій.

Що таке Lock in Java?

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

Багатопотокова програма з синхронізацією

Багатопотокова програма це метод або блок, захищений від втручання з боку інших потоків, які спільно використовують той самий ресурс, що вказується за допомогою ключового слова `synchronized`.

Використання синхронізованого методу

Будь-який метод, оголошений як синхронізований, називається синхронізованим методом. Він також використовується для блокування об'єкта для будь-якого спільного ресурсу. Отже, коли потік викликає синхронізований метод. Він автоматично блокує цей об’єкт і звільняє його, коли завершить своє завдання.

Примітка: Ключове слово synchronized не може працювати з класами та змінними. З ключовим словом можна використовувати лише методи та блоки.

Навіщо використовувати Syncхронізований метод?

  • Він використовується для блокування об'єкта для будь-яких спільних ресурсів.
  • Об’єкт отримує блокування кожного разу, коли викликається синхронізований метод.
  • Блокування не знімається, доки нитка не виконає свою функцію

Синтаксис:

Acess_modifiers synchronized return_type method_name (Method_Parameters) {
}
class MathService {
    synchronized void getSumOfArray(int[] numbers) {
     int sum = 0;

         for (int number : numbers) {
             System.out.println(Thread.currentThread()
                     .getName()
                     + " adds "
                     + sum + " to "
                     + number + " to get -> "
                     + (sum += number));

             try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
                 throw new RuntimeException(e);
             }
         }
    }
}
public class Synchronization {
    public static void main(String[] args) {
        MathService mathService = new MathService();

        Thread threadOne = new Thread(() ->
                mathService.getSumOfArray(new int[]{10, 11, 12}));
        Thread threadTwo = new Thread(() ->
                mathService.getSumOfArray(new int[]{20, 21, 22}));

        threadOne.start();
        threadTwo.start();
    }
}

Пояснення коду:

Запустіть цей приклад і спостерігайте, що потік `0` спочатку отримує блокування об'єкта `mathService` і використовує це блокування винятково, доки не завершить виконання. Нитки "0" і "1" не чергуються в цьому коді. Результат виглядає як показано нижче.

вихід:

Thread-0 adds 0 to 10 to get -> 10
Thread-0 adds 10 to 11 to get -> 21
Thread-0 adds 21 to 12 to get -> 33
Thread-1 adds 0 to 20 to get -> 20
Thread-1 adds 20 to 21 to get -> 41
Thread-1 adds 41 to 22 to get -> 63

Використання синхронізованого блоку

Припустімо, що ви не хочете синхронізувати весь метод. Замість цього ви хочете синхронізувати кілька рядків коду. У той час, SyncХронізований блок допоміг синхронізувати вибраний Java Код. Syncдоступ до хронічних блокувань методів здійснюється на методі, тоді як синхронізовані блокування блоків доступні на об’єкті.

class MathService {
    void getSumOfArray(int[] numbers) {
        synchronized (this){
            int sum = 0;

            for (int number : numbers) {
                System.out.println(Thread.currentThread()
                        .getName()
                        + " adds "
                        + sum + " to "
                        + number + " to get -> "
                        + (sum += number));

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
}
public class Synchronization {
    public static void main(String[] args) {
        MathService mathService = new MathService();

        Thread threadOne = new Thread(() ->
                mathService.getSumOfArray(new int[]{10, 11, 12}));
        Thread threadTwo = new Thread(() ->
                mathService.getSumOfArray(new int[]{20, 21, 22}));

        threadOne.start();
        threadTwo.start();
    }
}

Пояснення коду:

Запустивши цей код, ви помітите, що він працює без будь-яких перешкод. У синхронізованому методі блокування застосовано методом, а в синхронізованому блоці блокування застосовано об’єктом. Переконайтеся, що вихідні дані відповідають малюнку нижче.

вихід:

Thread-0 adds 0 to 10 to get -> 10
Thread-0 adds 10 to 11 to get -> 21
Thread-0 adds 21 to 12 to get -> 33
Thread-1 adds 0 to 20 to get -> 20
Thread-1 adds 20 to 21 to get -> 41
Thread-1 adds 41 to 22 to get -> 63

Пояснення коду:

Коли ви запустите цей код, ви помітите, що він працює без перешкод, чого ми й очікували. У синхронізованому методі блокування застосовує метод, а в синхронізованому блочному методі блокування застосовує об’єкт.

Використання статичної синхронізації

In Java синхронізації, якщо існує більше одного об’єкта, два потоки можуть отримати блокування та ввійти в синхронізований блок або блок з окремим блокуванням для кожного об’єкта. Щоб уникнути цього, можна використовувати статичну синхронізацію. Syncхронізовані ключові слова будуть використовуватися перед статичними методами.

Примітка: У статичній синхронізації доступ до блокування надається класу, а не об’єкту та методу.

Код для демонстрації проблеми блокування кількох об’єктів

class MathService {
    synchronized void getSumOfArray(int[] numbers) {
            int sum = 0;

            for (int number : numbers) {
                System.out.println(Thread.currentThread()
                        .getName()
                        + " adds "
                        + sum + " to "
                        + number + " to get -> "
                        + (sum += number));

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
    }
}
public class Synchronization {
    public static void main(String[] args) {
        MathService mathService = new MathService();
        MathService mathService1 = new MathService();

        Thread threadOne = new Thread(() ->
                mathService.getSumOfArray(new int[]{10, 11, 12}));
        Thread threadTwo = new Thread(() ->
                mathService.getSumOfArray(new int[]{20, 21, 22}));
        Thread threadThree = new Thread(() ->
                mathService1.getSumOfArray(new int[]{10, 11, 12}));
        Thread threadFour = new Thread(() ->
                mathService1.getSumOfArray(new int[]{20, 21, 22}));

        threadOne.start();
        threadTwo.start();
        threadThree.start();
        threadFour.start();
    }
}

Пояснення коду:

Коли ми створюємо ще один екземпляр `MathService`, ми створюємо перешкоди в потоках, оскільки вони будуть чергуватися з двома об’єктами. Зауважте, що потік «0» і потік «2» чергуються з двома об’єктами, тоді як потоки «1» і «3» чергуються з двома об’єктами.

вихід:

Thread-0 adds 0 to 10 to get -> 10
Thread-2 adds 0 to 10 to get -> 10
Thread-0 adds 10 to 11 to get -> 21
Thread-2 adds 10 to 11 to get -> 21
Thread-0 adds 21 to 12 to get -> 33
Thread-2 adds 21 to 12 to get -> 33
Thread-1 adds 0 to 20 to get -> 20
Thread-3 adds 0 to 20 to get -> 20
Thread-1 adds 20 to 21 to get -> 41
Thread-3 adds 20 to 21 to get -> 41
Thread-1 adds 41 to 22 to get -> 63
Thread-3 adds 41 to 22 to get -> 63

Той самий код із використанням синхронізованого статичного методу

class MathService {
    synchronized static void getSumOfArray(int[] numbers) {
            int sum = 0;

            for (int number : numbers) {
                System.out.println(Thread.currentThread()
                        .getName()
                        + " adds "
                        + sum + " to "
                        + number + " to get -> "
                        + (sum += number));

                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
    }
}
public class Synchronization {
    public static void main(String[] args) {
        MathService mathService = new MathService();
        MathService mathService1 = new MathService();

        Thread threadOne = new Thread(() ->
                mathService.getSumOfArray(new int[]{10, 11, 12}));
        Thread threadTwo = new Thread(() ->
                mathService.getSumOfArray(new int[]{20, 21, 22}));
        Thread threadThree = new Thread(() ->
                mathService1.getSumOfArray(new int[]{10, 11, 12}));
        Thread threadFour = new Thread(() ->
                mathService1.getSumOfArray(new int[]{20, 21, 22}));

        threadOne.start();
        threadTwo.start();
        threadThree.start();
        threadFour.start();
    }
}

Запустіть наведений вище код і зауважте, що ми усунули перешкоди потоку. Вихід коду показано нижче.

вихід:

Thread-0 adds 0 to 10 to get -> 10
Thread-0 adds 10 to 11 to get -> 21
Thread-0 adds 21 to 12 to get -> 33
Thread-3 adds 0 to 20 to get -> 20
Thread-3 adds 20 to 21 to get -> 41
Thread-3 adds 41 to 22 to get -> 63
Thread-2 adds 0 to 10 to get -> 10
Thread-2 adds 10 to 11 to get -> 21
Thread-2 adds 21 to 12 to get -> 33
Thread-1 adds 0 to 20 to get -> 20
Thread-1 adds 20 to 21 to get -> 41
Thread-1 adds 41 to 22 to get -> 63

Переваги використання синхронізації

Ось переваги роботи з одночасними програмами:

  • Основна мета синхронізації в Java полягає в тому, щоб запобігти неузгодженим даним шляхом запобігання перешкод потоку.
  • Синхронізоване ключове слово в Java забезпечує блокування, яке забезпечує взаємовиключний доступ до спільного ресурсу та запобігає гонці даних.
  • Це також запобігає зміні порядку операторів коду компілятор, що може спричинити незначну одночасну проблему, якщо ми не використовуємо змінні або синхронізовані ключові слова.
  • SyncКлючове слово hronized зчитує дані з основної пам'яті, ніж з кешу, і коли воно знімає блокування.
  • Він також очищає операції запису з основної пам’яті, усуваючи помилки невідповідності пам’яті.

Недоліки SyncМеханізм хронізації

SyncМеханізми хронізації мають низьку продуктивність.

Наприклад

  • Припустимо, що існує п’ять процесів: A1, A2, A3, A4 і A5.
  • Вони чекають, поки спільні ресурси отримають доступ до одного потоку за раз.
  • Усі процеси залишаються в режимі очікування, тому останній у черзі повинен чекати, поки не завершаться всі інші процеси.

Підсумки

  • SyncХронізація відноситься до здатності контролювати доступ кількох потоків до будь-якого спільного ресурсу.
  • Java має два типи методів синхронізації: 1) Синхронізація процесів і 2) Синхронізація потоків.
  • Зафіксувати Java будується навколо внутрішньої сутності, відомої як монітор або замок.
  • Багатопотокова програма — це метод або блок, захищений від втручання з боку інших потоків, які спільно використовують той самий ресурс, що вказується за допомогою ключового слова `synchronized`.
  • Будь-який метод, який оголошено як синхронізований, називається синхронізованим методом.
  • In Javaдоступ до синхронізованих блокувань методів здійснюється в методі, тоді як доступ до блокувань синхронізованих блоків здійснюється в об’єкті.
  • У статичній синхронізації доступ до блокування надається класу, а не об’єкту та методу.
  • Основна мета синхронізації в Java полягає в тому, щоб запобігти неузгодженим даним шляхом запобігання перешкод потоку.
  • Найбільшим недоліком цього методу є те, що всі процеси залишаються в режимі очікування, тому останній у черзі повинен чекати, поки не завершаться всі інші процеси.

Щоденний інформаційний бюлетень Guru99

Розпочніть свій день з останніх та найважливіших новин про штучний інтелект, які ви можете знайти просто зараз.