JavaRush /Java блог /Random UA /Синхронізація потоків, блокування об'єкта та блокування к...
CynepHy6
34 рівень
Великий Новгород

Синхронізація потоків, блокування об'єкта та блокування класу

Стаття з групи Random UA
Синхронізація потоків, блокування об'єкта та блокування класу - 1Синхронізація відноситься до багатопоточності. Синхронізований блок коду може бути виконаний лише одним потоком одночасно. Java підтримує кілька потоків для виконання. Це може призвести до того, що два або більше потоків отримають доступ до одного і того ж поля або об'єкта. Синхронізація це процес, який дозволяє виконувати всі паралельні потоки у програмі синхронно. Синхронізація дозволяє уникнути помилок узгодженості пам'яті, викликаних через непослідовний доступ до спільної пам'яті. Коли метод оголошений як синхронізований, нитка тримає монітор для об'єкта, метод якого виконується. Якщо інший потік виконує синхронізований метод, ваш потік заблокується, поки інший потік не відпустить монітор. Синхронізація досягається у Java використанням зарезервованого словаsynchronized. Ви можете використовувати його у своїх класах, визначаючи синхронізовані методи або блоки. Ви не зможете використовувати synchronizedу змінних чи атрибутах у визначенні класу.

Блокування на рівні об'єкту

Це механізм синхронізації не статичного методу або статичного блоку коду, такий, що тільки один потік зможе виконати даний блок або метод на даному екземплярі класу. Це потрібно робити завжди, коли потрібно зробити дані на рівні екземпляра потокобезпечними. Приклад:
public class DemoClass{
    public synchronized void demoMethod(){}
}
або
public class DemoClass{
    public void demoMethod(){
        synchronized (this)        {
            //other thread safe code
        }
    }
}
або
public class DemoClass{
    private final Object lock = new Object();
    public void demoMethod(){
        synchronized (lock)        {
            //other thread safe code
        }
    }
}

Блокування на рівні класу

Запобігає можливості кільком потокам увійти до синхронізованого блоку під час виконання в будь-якому з доступних екземплярів класу. Це означає, що якщо під час виконання програми є 100 екземплярів класу DemoClass, то тільки один потік у цей час зможе виконати demoMethod()в будь-якому випадку, і всі інші випадки будуть заблоковані для інших потоків. Це необхідно, коли потрібно зробити статичні дані потокобезпечними.
public class DemoClass{
    public synchronized static void demoMethod(){}
}
або
public class DemoClass{
    public void demoMethod(){
        synchronized (DemoClass.class)        {
            //other thread safe code
        }
    }
}
або
public class DemoClass
{
    private final static Object lock = new Object();
    public void demoMethod(){
        synchronized (lock)        {
            //other thread safe code
        }
    }
}

Деякі важливі зауваження

  1. Синхронізація Java гарантує, що жодні два потоки не зможуть виконати синхронізований метод одночасно або паралельно.

  2. synchronizedможна використовувати лише з методами та блоками коду. Ці методи або блоки можуть бути статичними або нестатичні.

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

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

  5. Синхронізація в Java буде кидати NullPointerException, якщо об'єкт використовується в синхронізованому блоці null. Наприклад, у наведеному вище прикладі коду, якщо замок ініціалізується як null, синхронізований (lock) кине NullPointerException.

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

  7. Цілком можливо, що статичний і не статичний синхронізовані методи можуть працювати одночасно або паралельно, тому що вони захоплюють замок на інший об'єкт.

  8. Відповідно до специфікації мови, ви не можете використовувати synchronizedв конструкторі це призведе до помилки компіляції.

  9. Не синхронізуйте по не фінальному (no final) полю, тому що посилання на не фінальне поле може змінитися в будь-який час, а потім інший потік може отримати синхронізацію на різних об'єктах і вже не буде жодної синхронізації взагалі. Найкраще використовувати клас String, який вже незмінний та фінальний.

Удачі у навчанні!! Оригінал: Object level lock vs Class level lock in Java
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ