Що означає "синхронізований"?


993

У мене є деякі питання щодо використання та значення synchronizedключового слова.

  • Яке значення synchronizedключового слова?
  • Коли повинні бути методи synchronized?
  • Що це означає програмно та логічно?


1
корисно обговорення між HashMap і Hashtable, і синхронізація: stackoverflow.com/questions/40471/java-hashmap-vs-hashtable
LIMC

2
Можливий дублікат того, як працює синхронізація на Яві
Marian Paździoch

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

Відповіді:


878

synchronizedКлючове слово все про різних потоків читання та запису одних і тих же змінних, об'єктів і ресурсів. Це не тривіальна тема на Java, але ось цитата від Sun:

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

Дуже дуже маленькою оболонкою: Коли у вас є два потоки, які читають і записують на один і той же "ресурс", скажімо, змінна назва foo, вам потрібно забезпечити доступ цих змінних атомним способом. Без synchronizedключового слова, ваш потік 1 може не бачити змінну нитку 2, зроблену foo, або ще гірше, вона може бути лише наполовину змінена. Це не буде те, що ви логічно очікуєте.

Знову ж таки, це нетривіальна тема на Java. Щоб дізнатися більше, вивчіть тут теми про SO та Interwebs про:

Продовжуйте досліджувати ці теми, поки ім'я "Брайан Гец" не стане назавжди пов'язаним з терміном "паралельність" у вашому мозку.


71
Отже, в основному це ключове слово синхронізовано робить ваші методи безпечними для потоків?
Rigo Vides

82
Синхронізоване ключове слово є одним із інструментів, що роблять безпечний потік коду. Просто використання синхронізованого методу чи змінної саме по собі може чи не може зробити трюк. Базове розуміння моделі пам'яті Java дуже важливо для правильності одночасності.
Стю Томпсон

28
Якщо ви не Брайан Гец (або, можливо, Джон Скіт), майже неможливо отримати правильність паралельності Java лише з мовними примітивами (синхронізованими, мінливими). Для початку скористайтеся пакетом java.util.concurrent і надбавте це.
Тіло

12
Більш чітко: синхронізовані методи не можна викликати одночасно з декількох потоків.
петерх

2
Синхронізований @peterh робить більше, ніж це, отже, більш детальне пояснення
Стю Томпсон,

293

Ну, я думаю, нам було достатньо теоретичних пояснень, тому врахуйте цей код

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

Примітка: synchronizedблокує виклик наступного потоку до методу test (), поки виконання попереднього потоку не закінчено. Нитки можуть отримати доступ до цього методу по одному. Без synchronizedусіх потоків можна отримати доступ до цього методу одночасно.

Коли потік викликає синхронізований метод "тестування" об'єкта (тут об'єкт є екземпляром класу "TheDemo"), він отримує блокування цього об'єкта, будь-який новий потік не може викликати БУДЬ-який синхронізований метод того ж об'єкта, як і попередній потік який придбав замок, він не відпускає замок.

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

Вихід із синхронізованим

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Виведення без синхронізації

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9

7
Чудовий приклад, добре знати теорію, але код завжди більш конкретний і повний.
Санті Іглесіас

2
@SantiIglesias "Повна"? Ні. Цей приклад демонструє поведінку блокування synchronized, але послідовність пам'яті ігнорується.
Стю Томпсон

2
Послідовність пам'яті @Сту Томпсона є результатом блокування
Dheeraj Sachan

@DheerajSachan За такою логікою використання ReentrantLock призведе до послідовності пам'яті. Це не так.
Стю Томпсон

3
@boltup_im_coding: Метод start () ставить Thread у стан "RUNNABLE", це означає, що вона готова до виконання або вже виконується. Може статися, що інший потік (як правило, але не обов'язково з більш високим пріоритетом) у стані Runnable стрибає з черги та починає виконувати. У наведеному вище прикладі, ТРИ 3 вдалося отримати процесор перед ТРИВОЮ 2.
Sahil J

116

synchronizedКлючове слово запобігає одночасний доступ до блоку коди або об'єкта з допомогою декількох потоків. Усі методи Hashtableє synchronized, тому лише один потік може виконувати будь-який з них одночасно.

При використанні не- synchronizedконструкції типу HashMap, ви повинні побудувати функції безпеки потоків в вашому коді , щоб уникнути помилок узгодженості.


81

synchronizedозначає, що в середовищі з декількома synchronizedпотоками об'єкт, що має метод (и) / блок (и), не дозволяє двом потокам отримувати доступ до synchronizedметоду (ив) / блоку (кодів) коду одночасно. Це означає, що один потік не може читати, поки інший поновлює його.

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

Якщо ваша програма є однопоточною, synchronizedблоки не надають переваг.


54

synchronizedКлючове слово викликає потік , щоб отримати блокування при вході в методі, таким чином , що тільки один потік може виконати метод в той же час (для даного екземпляра об'єкта, якщо він не є статичним методом).

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

Врахуйте це:

 if (vector.isEmpty()){
     vector.add(data);
 }

Незважаючи на те, що залучені методи синхронізовані, оскільки вони блокуються та розблоковуються окремо, два, на жаль, приурочені потоки можуть створити вектор з двома елементами.

Таким чином, фактично вам також доведеться синхронізувати код свого додатка.

Оскільки синхронізація на рівні методів є а) дорогою, коли вона вам не потрібна, і b) недостатньою, коли вам потрібна синхронізація, зараз існують несинхронізовані заміни (ArrayList у випадку Vector).

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


26

Огляд

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

Синхронізоване ключове слово використовується для визначення блоку коду, де безліч потоків можуть отримати доступ до однієї змінної безпечним способом.

Глибше

Синтаксично synchronizedключове слово приймає Objectяк параметр (його називають об'єктом блокування ), за яким слідує a { block of code }.

  • Коли виконання стикається з цим ключовим словом, поточний потік намагається "заблокувати / придбати / володіти" (взяти свій вибір) об'єкта блокування та виконати відповідний блок коду після придбання блокування.

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

  • Лише одна нитка одночасно може утримувати замок, протягом цього часу всі інші потоки, які намагаються придбати той самий об’єкт блокування, будуть чекати (призупиняють їх виконання). Блокування буде звільнено, коли виконання вийде з блоку синхронізованого коду.

Синхронізовані методи:

Додавання synchronizedключового слова в визначення методу одно всього тіла методу загортають в синхронізований блоці коду з об'єктом блокування істотами this (для методів примірників) і ClassInQuestion.getClass() (для методів класу) .

- Метод екземпляра - це метод, який не має staticключового слова.
- Метод класу - це метод, який має staticключове слово.

Технічні

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

Недостатньо завершити операцію запису в потоці раніше (час настінного годинника) інший потік читає її, тому що апаратне забезпечення могло б кешувати значення змінної, і нитка читання побачила б кешоване значення замість того, що було записано в це.

Висновок

Таким чином, у випадку Java вам потрібно дотримуватися моделі пам'яті Java, щоб упевнитись, що помилки при нанизуванні не трапляються.
Іншими словами: Використовуйте синхронізацію, атомні операції або класи, які використовують їх для вас під кришками.

Джерела

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Специфікація мови Java®, 2015-02-13


Вибачте, але я маю цей приклад, і я не розумію значення: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); синхронізований (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. Чому ви викликали блок у першій інстанції, і це виклик не впливає на код? 2. Другий екземпляр буде безпечним для потоків, незважаючи на виклик блоку на перший?
Adryr83

1
@ Adryr83 Якщо у вас є питання, ви, ймовірно, можете його задати, розмістивши нове запитання. Але оскільки ми тут, я розберу, що я можу (ваше питання трохи важко зрозуміти). З того, що я можу розповісти про цей фрагмент коду, він, схоже, не містить нічого, що вимагає синхронізації. Це поза контекстом. Пропозиція: Якщо ви можете, спробуйте розділити код на менші окремі фрагменти, а потім знайдіть відповіді на них. Набагато простіше намагатися зрозуміти дрібні та поодинокі проблеми, ніж намагатися з'ясувати один великий блок коду.
Gima

21

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


16

Що таке ключове слово синхронізоване?

Нитки спілкуються головним чином шляхом спільного доступу до полів і посилань на посилання на об'єкти. Така форма спілкування є надзвичайно ефективною, але робить можливими два види помилок: втручання в потоки та помилки послідовності пам'яті . Інструментом, необхідним для запобігання цих помилок, є синхронізація.

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

Коли методи синхронізовані?

Методи синхронізуються, коли ви додаєте synchronizedдо визначення методу чи декларації. Ви також можете синхронізувати певний блок коду за допомогою методу.

Що це означає програматично та логічно?

Це означає, що лише один потік може отримати доступ до критичної секції , придбавши замок. Якщо цей потік не звільнить цей замок, усім іншим потокам (ім) доведеться чекати, щоб придбати замок. Вони не мають доступу для входу в критичну секцію із придбанням блокування.

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

Більше інформації на сторінці документації Java

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

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

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

Кажуть, що нитка володіє внутрішнім замком між часом, коли вона придбала замок і відпустила замок. Поки нитка володіє власним замком, жодна інша нитка не може придбати такий самий замок. Інший потік блокується при спробі придбати замок.

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

Синхронізація методів має два ефекти :

По-перше, неможливо переплутати два виклики синхронізованих методів на одному об’єкті.

Коли одна нитка виконує синхронізований метод для об'єкта, всі інші потоки, які викликають синхронізовані методи для одного блоку об'єктів (призупинення виконання), поки перший потік не буде виконано з об'єктом.

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

Це гарантує, що зміни стану об'єкта є видимими для всіх потоків.

Шукайте інші альтернативи синхронізації в:

Уникайте синхронізації (цього) на Java?


11

Synchronized normal methodеквівалент Synchronized statement(використовувати це)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static methodеквівалент Synchronized statement(клас використання)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Синхронізований оператор (використовуючи змінну)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

Бо synchronizedми маємо і те, Synchronized Methodsі Synchronized Statements. Однак Synchronized Methodsце схоже на Synchronized Statementsте, що нам просто потрібно зрозумітиSynchronized Statements .

=> В основному, у нас буде

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

Ось 2 думки, які допомагають зрозуміти synchronized

  • Кожен об’єкт / клас має intrinsic lockасоційований з ним.
  • Коли потік викликає a synchronized statement, він автоматично отримує значення intrinsic lockдля цього synchronized statement'sоб'єкта і звільняє його, коли метод повертається. Поки нитка володіє антенною intrinsic lock, НІЙ інший потік не може придбати SAME lock => thread safe.

=> Коли thread Aвикликає synchronized(this){// code 1}=> весь код блоку (внутрішній клас), де have synchronized(this)і all synchronized normal method(всередині класу) заблокований, оскільки блокування SAME . Він буде виконуватися післяthread A розблокування ("// код 1" завершено).

Така поведінка схожа на synchronized(a variable){// code 1}або synchronized(class).

САМЕ ЗАКЛЮЧЕННЯ => замок (не залежить від того, який метод? Чи які заяви?)

Використовувати синхронізований метод або синхронізовані оператори?

Я вважаю за краще, synchronized statementsтому що вона більш розширювана. Наприклад, у майбутньому вам потрібно лише синхронізувати частину методу. Наприклад, у вас є 2 синхронізовані методи, і вони не мають жодного відношення один до одного, однак, коли потік запускає метод, він блокує інший метод (це може запобігти використанню synchronized(a variable)).

Однак застосувати синхронізований метод просто, а код виглядати просто. Для деяких класів існує лише 1 синхронізований метод або всі синхронізовані методи у класі, що відповідають один одному => ми можемо використовувати, synchronized methodщоб зробити код коротшим і легшим для розуміння

Примітка

(це не стосується великої кількості synchronized, це різниця між об'єктом і класом або нестатичною і статичною).

  • При використанні synchronizedабо звичайний метод або synchronized(this)або synchronized(non-static variable)вона буде синхронізована база кожного примірника об'єкта.
  • При використанні synchronizedабо статичного методу, synchronized(class)або synchronized(static variable)він синхронізується на базі класу

Довідково

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Сподіваюся, це допоможе


11

Ось пояснення з навчальних посібників Java .

Розглянемо наступний код:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

якщо countце примірник SynchronizedCounter, то синхронізація цих методів має два ефекти:

  • По-перше, неможливо переплутати два виклики синхронізованих методів на одному об’єкті. Коли одна нитка виконує синхронізований метод для об'єкта, всі інші потоки, які викликають синхронізовані методи для того ж блоку об'єктів (призупинення виконання), поки перший потік не буде виконано з об'єктом.
  • По-друге, при виході синхронізованого методу він автоматично встановлює зв'язок, що відбувається раніше, з будь-яким наступним викликом синхронізованого методу для того ж об'єкта. Це гарантує, що зміни стану об'єкта є видимими для всіх потоків.

9

Наскільки я розумію, синхронізований в основному означає, що компілятор записує monitor.enter і monitor.exit навколо вашого методу. Як такий, він може бути безпечним для потоків залежно від способу його використання (я маю на увазі, що ви можете написати об'єкт синхронізованими методами, який не є безпечним для потоків, залежно від того, що робить ваш клас).


5

Те, що інші відповіді відсутні, є одним із важливих аспектів: бар'єри пам’яті . Синхронізація нитки в основному складається з двох частин: серіалізації та видимості. Я раджу всім google щодо "бар'єру пам'яті jvm", оскільки це нетривіальна і надзвичайно важлива тема (якщо ви змінюєте спільні дані, до яких звертаються декілька потоків). Зробивши це, я раджу переглядати класи пакунків java.util.concurrent, які допомагають уникнути використання явної синхронізації, що, в свою чергу, допомагає зберігати програми просто та ефективно, можливо, навіть запобігаючи тупиковість.

Одним із таких прикладів є ConcurrentLinkedDeque . Разом з командним шаблоном це дозволяє створювати високоефективні робочі потоки шляхом введення команд у паралельну чергу - не потрібна явна синхронізація, неможливі тупикові місця, не потрібно явного сну (), просто запитуйте чергу, зателефонувавши take ().

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

Ефекти узгодженості пам’яті: Як і в інших одночасних колекціях, дії в потоці перед розміщенням об'єкта в ConcurrentLinkedDeque відбуваються перед діями, наступними після доступу або видалення цього елемента з ConcurrentLinkedDeque в іншому потоці.

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


3

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

class MyRunnable implements Runnable {
    int var = 10;
    @Override
    public void run() {
        call();
    }

    public void call() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                var++;
                System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
            }
        }
    }
}

public class MutlipleThreadsRunnable {
    public static void main(String[] args) {
        MyRunnable runnable1 = new MyRunnable();
        MyRunnable runnable2 = new MyRunnable();
        Thread t1 = new Thread(runnable1);
        t1.setName("Thread -1");
        Thread t2 = new Thread(runnable2);
        t2.setName("Thread -2");
        Thread t3 = new Thread(runnable1);
        t3.setName("Thread -3");
        t1.start();
        t2.start();
        t3.start();
    }
}

Ми створили два об’єкти класу MyRunnable, якими можна поділитись за допомогою потоку 1 та потоком 3 та runnable2 лише з потоком 2. Тепер, коли t1 і t3 починається без синхронізованого використання, вихід PFB, який дозволяє припустити, що обидва потоки 1 і 3 одночасно впливають на значення var, де для потоку 2 var має власну пам'ять.

Without Synchronized keyword

    Current Thread Thread -1 var value 11
    Current Thread Thread -2 var value 11
    Current Thread Thread -2 var value 12
    Current Thread Thread -2 var value 13
    Current Thread Thread -2 var value 14
    Current Thread Thread -1 var value 12
    Current Thread Thread -3 var value 13
    Current Thread Thread -3 var value 15
    Current Thread Thread -1 var value 14
    Current Thread Thread -1 var value 17
    Current Thread Thread -3 var value 16
    Current Thread Thread -3 var value 18

Використовуючи Synchronzied, нитка 3 чекає завершення потоку 1 у всіх сценаріях. Існує два замикання блокування, один на runnable1, розділений на потік 1 і на потік 3, а інший на runnable2, розділений лише на потік 2.

Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18

Синхронізованість означає навіть більше: це має глибокий вплив на бар'єр пам'яті.
користувач1050755

1

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

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

Object.wait()

0

synchronizedблок на Java - це монітор у багатопотоковому читанні. synchronizedблок з тим самим об'єктом / класом може бути виконаний лише одним потоком, всі інші чекають. Це може допомогти в race conditionситуації, коли кілька потоків намагаються оновити ту саму змінну (перший крок - використання volatileAbout )

Java 5розширено synchronizedпідтримкою happens-before[Про нас]

Розблокування (синхронізований блок або вихід методу) монітора відбувається перед кожним наступним блокуванням (синхронізований блок або запис методу) того самого монітора.

Наступний крок - java.util.concurrent

непостійний проти синхронізований


-6

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.