Что означает «синхронизированный»?

У меня есть несколько вопросов, касающихся использования и значенияsynchronized ключевое слово.

What is the significance of the synchronized keyword? When should methods be synchronized? What does it mean programmatically and logically?
 Marian Paździoch08 авг. 2016 г., 17:46
 limc22 янв. 2011 г., 19:42
полезное обсуждение между hashmap и hashtable и синхронизация: Stackoverflow.com / вопросы / 40471 / Java-HashMap-против-Хеш

Ответы на вопрос(15)

который можно найти на футбольном поле. Есть параллельные группы людей, желающих войти, но на турникете они «синхронизированы». Только один человек за раз может пройти. Все, кто хочет пройти, сделают, но, возможно, им придется подождать, пока они не смогут пройти.

Synchronized normal method эквивалентноSynchronized statement (использовать этот

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

    equivalent to

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

Synchronized static method эквивалентноSynchronized statement (использовать класс)


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

    equivalent to

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

Синхронизированный оператор (с использованием переменной)


    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 
}

Вот, думаю, это поможет понятьsynchronized

Каждый объект / класс имеетintrinsic lock связано с этим. Когда поток вызываетsynchronized statement, он автоматически получаетintrinsic lock для этогоsynchronized statement's объект и освобождает его при возврате метода. Пока поток владеетintrinsic lock, НЕТ другого поток может получитьОДНО И ТОЖ lock => потокобезопасен.

=> Когдаthread A вызываетsynchronized(this){// code 1} => весь код блока (внутри класса), где естьsynchronized(this) и всеsynchronized normal method (внутри класса) заблокирован, потому чтоОДНО И ТОЖ замок. Будет выполняться послеthread A разблокировать ("// код 1" закончен).

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

SAME LOCK => блокировка (не зависит от того, какой метод? или какие операторы?)

Использовать синхронизированный метод или синхронизированные операторы?

Я предпочитаю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.htm https: //docs.oracle.com/javase/tutorial/essential/concurrency/locksync.htm

Надеюсь, это поможет

 Adryr8326 янв. 2019 г., 11:40
Извините, но у меня есть этот пример, и я не понимаю значения: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); synchronized (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. Почему вы вызываете блок в первом экземпляре, и этот вызов не влияет на код? 2. Второй экземпляр будет поточно-ориентированным, несмотря на вызов блока на первом?

я думаю, у нас было достаточно теоретических объяснений, поэтому рассмотрим этот код

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 все потоки могут получить доступ к этому методу одновременно.

Когда поток вызывает синхронизированный метод 'test' объекта (здесь объект является экземпляром класса '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
 Sourabh Bhagat30 янв. 2017 г., 06:31
потрясающее объяснение
 Santi Iglesias08 сент. 2016 г., 08:15
Отличный пример, полезно знать теорию, но код всегда более конкретный и полный.
 Stu Thompson01 февр. 2017 г., 23:57
@ SantiIglesias "Complete"? Нет. Этот пример демонстрирует поведение блокировкиsynchronized, но согласованность памяти игнорируется.
 Dheeraj Sachan02 февр. 2017 г., 10:55
@ Stu целостность памяти Томпсона - результат блокировки
 Sahil J07 апр. 2017 г., 08:07
@ boltup_im_coding: метод start () переводит Thread в состояние «RUNNABLE», что означает, что он готов к выполнению или уже выполняется. Может случиться, что другой поток (обычно, но не обязательно с более высоким приоритетом) в состоянии Runnable переходит в очередь и начинает выполнение. В приведенном выше примере THREAD 3 получала процессор до THREAD 2.

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

Threads взаимодействуют, главным образом, путем совместного доступа к полям и ссылкам на объекты, на которые ссылаются поля. Эта форма общения чрезвычайно эффективна, но допускает два вида ошибок: ошибки интерференции и ошибки памяти. Инструмент, необходимый для предотвращения этих ошибок, - это синхронизация.

Синхронизированные блоки или методы предотвращают взаимодействие потоков и обеспечивают согласованность данных. В любой момент времени только один поток может получить доступ к синхронизированному блоку или методу критический раздел) приобретая замок. Другие потоки будут ожидать освобождения блокировки для доступа к критический раздел.

Когда методы синхронизируются?

Методы синхронизируются при добавленииsynchronized к определению или объявлению метода. Вы также можете синхронизировать определенный блок кода с помощью метода.

Что значит про грамматически и логически?

Это означает, что только один поток может получить доступ к критический раздел приобретая замок. Если этот поток не снимет эту блокировку, все остальные потоки должны будут ждать блокировки. У них нет доступа для ввода критический раздел без блокировки.

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

Более подробная информация из документации по Java Страницы

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

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

Каждый объект имеет встроенную блокировку, связанную с ним. По соглашению поток, которому требуется исключительный и согласованный доступ к полям объекта, должен получить внутреннюю блокировку объекта перед тем, как получить к ним доступ, а затем снять внутреннюю блокировку, когда это будет сделано с ними.

Говорят, что поток владеет внутренней блокировкой между моментом, когда он получил блокировку и снял ее. Пока поток владеет внутренней блокировкой, никакой другой поток не может получить такую же блокировку. Другой поток заблокируется, когда попытается получить блокировку.

Когда поток освобождает внутреннюю блокировку, между этим действием и любым последующим получением той же блокировки устанавливается взаимосвязь «происходит до того».

Методы синхронизации синхронизированы с двумяпоследстви:

Во-первых, невозможно вызвать два чередования синхронизированных методов для одного и того же объекта.

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

Во-вторых, при выходе из синхронизированного метода он автоматически устанавливает отношение «до и после» с любым последующим вызовом синхронизированного метода для того же объекта.

Это гарантирует, что изменения состояния объекта видны всем потокам.

Ищите другие альтернативы синхронизации в:

Избегать синхронизации (этого) в Java?

 Adryr8326 янв. 2019 г., 11:34
Извините, но у меня есть этот пример, и я не понимаю значения: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); synchronized (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. Почему вы вызываете блок в первом экземпляре, и этот вызов не влияет на код? 2. Второй экземпляр будет поточно-ориентированным, несмотря на вызов блока на первом?

synchronized означает, что в многопоточной среде объект, имеющийsynchronized method (s) / block (s) не позволяют двум потокам обращаться кsynchronized метод (ы) / блок (и) кода одновременно. Это означает, что один поток не может читать, а другой обновляет его.

Вместо этого второй поток будет ждать, пока первый поток завершит свое выполнение. Накладные расходы - это скорость, но преимущество - это согласованность данных.

Если ваше приложение однопоточное,synchronized блоки не дает преимуществ.

Решение Вопроса

synchronized Ключевое слово - это все о чтении и записи разных потоков в одни и те же переменные, объекты и ресурсы. Это не тривиальная тема в Java, но вот цитата из Sun:

synchronizedетоды @ обеспечивают простую стратегию предотвращения помех потоков и ошибок согласованности памяти: если объект виден более чем одному потоку, все операции чтения или записи в переменные этого объекта выполняются с помощью синхронизированных методов.

В очень, очень маленьких словах: Если у вас есть два потока, которые читают и пишут в один и тот же «ресурс», произнесите переменную с именемfoo, вам нужно убедиться, что эти потоки обращаются к переменной атомарным способом. Безsynchronized ключевое слово, ваша тема 1 может не видеть тему изменения 2, внесенную вfoo или, что еще хуже, он может быть изменен только наполовину. Это не будет тем, что вы ожидаете.

Снова, это нетривиальная тема в Java. Чтобы узнать больше, изучите темы здесь, в SO и Interwebs о:

Параллелизм Модель памяти Java

Продолжайте изучать эти темы до тех пор, пока имя "Брайан Гетц" становится постоянно связанным с термином "Параллелизм" в твоем мозгу.

 peterh15 мар. 2016 г., 13:35
Более четко: синхронизированные методы нельзя вызывать одновременно из нескольких потоков.
 Thilo06 июл. 2009 г., 09:30
Если вы не Брайан Гетц (или, может быть, Джон Скит), почти невозможно добиться правильного параллелизма Java только с помощью языковых примитивов (синхронизированных, изменчивых). Для начала воспользуйтесь пакетом java.util.concurrent и постройте его.
 Stu Thompson06 июл. 2009 г., 09:14
Синхронизированное ключевое слово - это один из инструментов, который делает ваш поток кода безопасным. Простое использование синхронизированного метода или переменной само по себе может или не может помочь. Для понимания правильности параллелизма очень важно иметь базовое понимание модели памяти Java.
 Stu Thompson12 апр. 2016 г., 17:53
@ peterh synchronized делает больше, чем это, следовательно, более подробное объяснение
 Rigo Vides06 июл. 2009 г., 09:12
Так что, в основном это ключевое слово Synchronized делает ваши методы поточно-ориентированными?

что никакие два потока не могут получить доступ к блоку / методу одновременно. Когда мы говорим, что любой блок / метод класса синхронизирован, это означает, что только один поток может получить к ним доступ одновременно. Внутренне поток, который пытается получить к нему доступ, сначала блокирует этот объект, и пока эта блокировка недоступна, никакой другой поток не может получить доступ ни к одному из синхронизированных методов / блоков этого экземпляра класса.

Примечание другой поток может получить доступ к методу того же объекта, который не определен для синхронизации. Поток может снять блокировку, вызвав

Object.wait()

synchronizedлючевое слово @ предотвращает одновременный доступ к блоку кода или объекта несколькими потоками. По умолчанию,Hashtable являетсяsynchronized, поэтому только один поток может получить доступ к таблице одновременно.

При использованииnon-synchronized конструирует какHashMap, вы должны встроить функции безопасности потоков в свой код, чтобы предотвратить ошибки согласованности памяти.

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

Это часто называют деланием класса потокобезопасным, но я бы сказал, что это эвфемизм. Несмотря на то, что синхронизация защищает внутреннее состояние вектора от повреждения, это обычно мало помогает пользователю вектора.

Учти это

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

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

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

Потому что синхронизация на уровне метода а) дорогая, когда она вам не нужна, и б) недостаточная, когда вам нужна синхронизация, теперь есть несинхронизированные замены (ArrayList в случае Vector).

Совсем недавно был выпущен пакет для параллелизма с несколькими умными утилитами, которые решают проблемы с многопоточностью.

 Adryr8326 янв. 2019 г., 11:35
Извините, но у меня есть этот пример, и я не понимаю значения: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); synchronized (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. Почему вы вызываете блок в первом экземпляре, и этот вызов не влияет на код? 2. Второй экземпляр будет поточно-ориентированным, несмотря на вызов блока на первом?

Учебники по 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, то синхронизация этих методов имеет два эффекта:

Во-первых, невозможно выполнить два вызова синхронизированных методов для одного и того же объекта. Когда один поток выполняет синхронизированный метод для объекта, все другие потоки, которые вызывают синхронизированные методы для того же блока объекта (приостанавливают выполнение), пока первый поток не завершится с объектом. Во-вторых, при выходе из синхронизированного метода он автоматически устанавливает отношение «до и после» с любым последующим вызовом синхронизированного метода для того же объекта. Это гарантирует, что изменения состояния объекта видны всем потокам.

что компилятор напишет monitor.enter и monitor.exit вокруг вашего метода. Таким образом, он может быть потокобезопасным в зависимости от того, как он используется (я имею в виду, что вы можете написать объект с синхронизированными методами, который не является потокобезопасным в зависимости от того, что делает ваш класс

что несколько потоков, если они связаны с одним объектом, могут предотвратить грязное чтение и запись, если синхронизированный блок используется для определенного объекта. Чтобы дать вам больше ясности, давайте возьмем пример:

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: runnable1 используется совместно с потоком 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

Использование Синхронизировано, поток 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
 user105075511 сент. 2017 г., 00:45
Синхронизированный означает еще больше: он оказывает глубокое влияние на барьер памяти.
Обзор

то есть когда несколько потоков читают или пишут одну и ту же переменную.
Это может происходить напрямую (с помощью доступа к той же переменной) или косвенно (с помощью класса, который использует другой класс, обращающийся к той же переменной).

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

Глубж

Синтаксисsynchronized ключевое слово принимаетObject как параметр (называется объект блокировки), за которым следует символ{ block of code }.

Когда выполнение встречает это ключевое слово, текущий поток пытается «заблокировать / приобрести / владеть» (выбрать) объект и выполнить связанный блок кода после получения блокировки.

Любые записи в переменные внутри блока синхронизированного кода гарантированно будут видны всем другим потокам, которые аналогичным образом выполняют код внутри блока синхронизированного кода, используя тот же объект.

Только один поток за раз может удерживать блокировку, в течение которой все другие потоки пытаются получить то же самое объект будет ждать (приостановить их выполнение). Блокировка будет снята, когда выполнение выйдет из блока синхронизированного кода.

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

Добавлениеsynchronizedлючевое слово @ для определения метода равно всему телу метода, заключенному в блок синхронизированного кода с объект будучиthis (например, методы) а такжеClassInQuestion.getClass() (для методов класса).

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

Техническая информация

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

Этого недостаточно для завершения операции записи в потоке до (время настенного времени), когда другой поток его читает, потому что аппаратное обеспечение могло бы кэшировать значение переменной, и поток чтения видел бы кэшированное значение вместо того, что было записано к нему.

Выво

Таким образом, в случае с Java вы должны следовать модели памяти Java, чтобы избежать ошибок потоков.
Другими словами: используйте синхронизацию, атомарные операции или классы, которые используют их для ва

Источники

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

 Gima28 янв. 2019 г., 10:59
@ Adryr83 Если у вас есть вопрос, вы можете задать его, разместив новый вопрос. Но так как мы здесь, я разберусь, что смогу (ваш вопрос немного сложен для понимания). Из того, что я могу сказать об этом куске кода, он не содержит ничего, что требует синхронизации. Это вне контекста. Предложение: Если вы можете, попробуйте разделить код на более мелкие отдельные части, а затем найдите ответы на эти вопросы. Гораздо проще пытаться понять небольшие и изолированные проблемы, чем пытаться выяснить один большой блок кода.
 Adryr8326 янв. 2019 г., 11:33
Извините, но у меня есть этот пример, и я не понимаю значения: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); synchronized (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + "" + i2); } `1. Почему вы вызываете блок в первом экземпляре, и этот вызов не влияет на код? 2. Второй экземпляр будет поточно-ориентированным, несмотря на вызов блока на первом?

барьеры памяти. Синхронизация потоков в основном состоит издв parts: сериализация и видимость. Я советую всем google для «барьера памяти jvm», поскольку это нетривиальная и чрезвычайно важная тема (если вы изменяете общие данные, к которым обращаются несколько потоков). Сделав это, я советую взглянуть на классы пакета java.util.concurrent, которые помогают избежать использования явной синхронизации, что, в свою очередь, помогает сделать программы простыми и эффективными, возможно, даже предотвращает взаимные блокировки.

Один из таких примеров - ConcurrentLinkedDeque. Вместе с шаблон команды позволяет создавать высокоэффективные рабочие потоки, помещая команды в параллельную очередь - явной синхронизации не требуется, тупиков не требуется, не требуется явный sleep (), просто опросите очередь, вызвав take ().

Короче говоря: "синхронизация памяти" происходит Неявно когда вы запускаете поток, поток заканчивается, вы читаете переменную, вы разблокируете монитор (оставляете синхронизированный блок / функцию) и т. д. Эта «синхронизация» влияет (в некотором смысле «сбрасывает»)вс пишет сделано до этого конкретного действия. В случае вышеупомянуто ConcurrentLinkedDeque документация "говорит":

Эффекты согласованности памяти: Как и в случае других параллельных коллекций, действия в потоке перед помещением объекта в ConcurrentLinkedDeque Случиться, прежде, чем действия после доступа или удаления этого элемента из ConcurrentLinkedDeque в другом потоке.

Это неявное поведение является несколько пагубным аспектом, потому что большинство Java-программистов без особого опыта просто примут из-за этого многое. А потом неожиданно наткнулся на этот поток после того, как Java не выполняет то, что «предполагается» делать в рабочей среде, где есть другая рабочая нагрузка - и довольно сложно проверить проблемы параллелизма.

Ваш ответ на вопрос