У меня есть несколько вопросов относительно использования и значимости synchronized
ключевого слова.
- Каково значение
synchronized
ключевого слова? - Когда должны быть методы
synchronized
? - Что это означает программно и логически?
java
multithreading
keyword
synchronized
Johanna
источник
источник
Ответы:
synchronized
Ключевое слово все о разных потоков чтения и записи одних и тех же переменных, объектов и ресурсов. Это не тривиальная тема в Java, но вот цитата из Sun:В двух словах: если у вас есть два потока, которые читают и записывают в один и тот же «ресурс», скажем, переменную с именем
foo
, вам нужно убедиться, что эти потоки обращаются к переменной атомарным способом. Безsynchronized
ключевого слова ваша ветка 1 может не видеть изменения, внесенные в ветку 2foo
, или, что еще хуже, она может быть изменена только наполовину. Это не будет то, что вы ожидаете логически.Опять же, это не тривиальная тема в Java. Чтобы узнать больше, изучите темы здесь, в SO и Interwebs:
Продолжайте изучать эти темы, пока имя «Брайан Гетц» не станет постоянно ассоциироваться с термином «параллелизм» в вашем мозгу.
источник
Ну, я думаю, у нас было достаточно теоретических объяснений, поэтому рассмотрим этот код
Примечание:
synchronized
блокирует вызов следующего потока для метода test () до тех пор, пока выполнение предыдущего потока не завершено. Потоки могут обращаться к этому методу по одному. Безsynchronized
всех потоков можно получить доступ к этому методу одновременно.Когда поток вызывает синхронизированный метод 'test' объекта (здесь объект является экземпляром класса 'TheDemo'), он получает блокировку этого объекта, любой новый поток не может вызвать ЛЮБОЙ синхронизированный метод того же объекта, пока предыдущий поток который приобрел замок, не снимает замок.
Подобное происходит, когда вызывается любой статический синхронизированный метод класса. Поток получает блокировку, связанную с классом (в этом случае любой нестатический синхронизированный метод экземпляра этого класса может быть вызван любым потоком, потому что эта блокировка уровня объекта все еще доступна). Любой другой поток не сможет вызвать какой-либо статический синхронизированный метод класса, если блокировка уровня класса не снята потоком, который в данный момент удерживает блокировку.
Выход с синхронизированным
Выход без синхронизации
источник
synchronized
, но согласованность памяти игнорируется.synchronized
Ключевое слово предотвращает одновременный доступ к блоку коды или объекта с помощью нескольких потоков. Все методыHashtable
естьsynchronized
, поэтому только один поток может выполнить любой из них одновременно.При использовании не-
synchronized
конструкций, таких какHashMap
, вы должны встроить функции безопасности потока в ваш код, чтобы предотвратить ошибки согласованности.источник
synchronized
означает, что в многопоточной среде объект, имеющийsynchronized
метод (-ы) / блок (-ы), не позволяет двум потокам одновременно обращаться кsynchronized
методу (-ам) / блоку (-ам) кода. Это означает, что один поток не может читать, а другой обновляет его.Вместо этого второй поток будет ждать, пока первый поток завершит свое выполнение. Накладные расходы - это скорость, но преимущество - это согласованность данных.
Если ваше приложение является однопоточным,
synchronized
блоки не дают преимуществ.источник
synchronized
Ключевое слово вызывает поток , чтобы получить блокировку при входе в методе, таким образом , что только один поток может выполнить метод в то же время (для данного экземпляра объекта, если он не является статическим методом).Это часто называют деланием класса потокобезопасным, но я бы сказал, что это эвфемизм. Хотя верно то, что синхронизация защищает внутреннее состояние вектора от повреждения, это обычно не сильно помогает пользователю вектора.
Учти это:
Несмотря на то, что используемые методы синхронизированы, поскольку они блокируются и разблокируются индивидуально, два, к сожалению, синхронизированных потока могут создать вектор с двумя элементами.
По сути, вы должны синхронизировать код приложения.
Поскольку синхронизация на уровне методов является а) дорогой, когда она вам не нужна, и б) недостаточной, когда вам нужна синхронизация, теперь есть несинхронизированные замены (ArrayList в случае Vector).
Совсем недавно был выпущен пакет для параллелизма с несколькими умными утилитами, которые решают проблемы с многопоточностью.
источник
обзор
Синхронизированное ключевое слово в Java связано с безопасностью потоков, то есть когда несколько потоков читают или записывают одну и ту же переменную.
Это может происходить напрямую (путем доступа к той же переменной) или косвенно (при использовании класса, который использует другой класс, который обращается к той же переменной).
Ключевое слово synchronized используется для определения блока кода, в котором несколько потоков могут безопасно обращаться к одной и той же переменной.
Глубже
Синтаксически
synchronized
ключевое слово принимает вObject
качестве параметра параметр (называемый объектом блокировки ), за которым следует символ{ block of code }
.Когда выполнение встречает это ключевое слово, текущий поток пытается «заблокировать / приобрести / владеть» (выбрать) заблокировать объект и выполнить связанный блок кода после того, как блокировка была получена.
Любые записи в переменные внутри блока синхронизированного кода гарантированно будут видны всем другим потокам, которые аналогичным образом выполняют код внутри блока синхронизированного кода, используя тот же объект блокировки .
Только один поток одновременно может удерживать блокировку, в течение которой все другие потоки, пытающиеся получить тот же самый объект блокировки, будут ожидать (приостановить их выполнение). Блокировка будет снята, когда выполнение выйдет из блока синхронизированного кода.
Синхронизированные методы:
Добавление
synchronized
ключевого слова в определение метода равно всего тела метода заворачивают в синхронизированном блоке кода с объектом блокировки существамиthis
(для методов экземпляров) иClassInQuestion.getClass()
(для методов класса) .- Метод экземпляра - это метод, который не имеет
static
ключевого слова.- Метод класса - это метод, который имеет
static
ключевое слово.технический
Без синхронизации не гарантируется, в каком порядке происходит чтение и запись, возможно, оставляя переменную с мусором.
(Например, переменная может закончиться с половиной битов, записанных одним потоком, и половиной битов, записанных другим потоком, оставляя переменную в состоянии, которое ни один из потоков не пытался записать, но объединенный беспорядок обоих.)
Недостаточно завершить операцию записи в потоке до (настенного времени), когда другой поток его прочитает, потому что аппаратное обеспечение могло бы кэшировать значение переменной, и поток чтения будет видеть кэшированное значение вместо того, что было записано в Это.
Вывод
Таким образом, в случае с Java вы должны следовать модели памяти Java, чтобы гарантировать, что ошибки потоков не возникнут.
Другими словами: используйте синхронизацию, атомарные операции или классы, которые используют их для вас.
источник
Думайте об этом как о турникете, который можно найти на футбольном поле. Есть параллельные группы людей, желающих войти, но на турникете они «синхронизированы». Только один человек за раз может пройти. Все, кто хочет пройти, сделают это, но им, возможно, придется подождать, пока они смогут пройти.
источник
Потоки взаимодействуют, главным образом, путем совместного доступа к полям и ссылкам на объекты, на которые ссылаются поля. Эта форма связи чрезвычайно эффективна, но допускает два вида ошибок: помехи потоков и ошибки согласованности памяти . Инструмент, необходимый для предотвращения этих ошибок - это синхронизация.
Синхронизированные блоки или методы предотвращают помехи потоков и обеспечивают согласованность данных. В любой момент времени только один поток может получить доступ к синхронизированному блоку или методу ( критическая секция ), получив блокировку. Другие потоки будут ожидать снятия блокировки для доступа к критическому разделу .
Методы синхронизируются при добавлении
synchronized
в определение или объявление метода. Вы также можете синхронизировать определенный блок кода с помощью метода.Это означает, что только один поток может получить доступ к критическому разделу , получив блокировку. Если этот поток не снимет эту блокировку, все остальные потоки должны будут ждать блокировки. У них нет доступа к критическому разделу без блокировки получения.
Это не может быть сделано с помощью магии. Программист обязан определить критические разделы в приложении и соответственно защитить их. Java обеспечивает платформу для защиты вашего приложения, но где и какие все разделы должны охраняться, является обязанностью программиста.
Подробнее на странице документации Java
Внутренние блокировки и синхронизация:
Каждый объект имеет встроенную блокировку, связанную с ним . По соглашению поток, которому требуется исключительный и согласованный доступ к полям объекта, должен получить внутреннюю блокировку объекта перед тем, как получить к ним доступ, а затем снять внутреннюю блокировку, когда это будет сделано с ними.
Говорят, что поток владеет внутренней блокировкой между моментом, когда он получил блокировку и снял ее. Пока потоку принадлежит внутренняя блокировка, никакой другой поток не может получить такую же блокировку. Другой поток заблокируется, когда попытается получить блокировку.
Синхронизация методов имеет два эффекта :
Когда один поток выполняет синхронизированный метод для объекта, все остальные потоки, которые вызывают синхронизированные методы для того же блока объекта (приостанавливают выполнение), пока первый поток не завершится с объектом.
Это гарантирует, что изменения состояния объекта видны всем потокам.
Ищите другие альтернативы синхронизации в:
Избегать синхронизации (это) в Java?
источник
Synchronized normal method
эквивалентноSynchronized statement
(используйте это)Synchronized static method
эквивалентноSynchronized statement
(используйте класс)Синхронизированный оператор (с использованием переменной)
Ибо
synchronized
у нас есть и тоSynchronized Methods
и другоеSynchronized Statements
. ОднакоSynchronized Methods
похоже наSynchronized Statements
то, что нам просто нужно понятьSynchronized Statements
.=> В основном мы будем иметь
Вот 2 думаю что поможет понимание
synchronized
intrinsic lock
связан с ним.synchronized statement
, он автоматически получаетintrinsic lock
для этогоsynchronized statement's
объекта и освобождает его при возврате метода. До тех пор, пока потоку принадлежит потокintrinsic lock
, никакой другой поток не может получить тот же самый поток = = безопасный поток.=> Когда
thread A
вызываетсяsynchronized(this){// code 1}
=> весь код блока (внутри класса), где есть,synchronized(this)
и всеsynchronized normal method
(внутри класса) заблокированы, потому что ЖЕ блокировка. Он будет выполнен послеthread A
разблокировки ("// код 1" завершен).Это поведение похоже на
synchronized(a variable){// code 1}
илиsynchronized(class)
.SAME LOCK => 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.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Надеюсь, это поможет
источник
Вот объяснение из Учебников Java .
Рассмотрим следующий код:
источник
Насколько я понимаю, синхронизированный в основном означает, что компилятор напишет monitor.enter и monitor.exit вокруг вашего метода. Таким образом, он может быть потокобезопасным в зависимости от того, как он используется (я имею в виду, что вы можете написать объект с синхронизированными методами, который не является потокобезопасным, в зависимости от того, что делает ваш класс).
источник
Чего не хватает другим ответам, так это одного важного аспекта: барьеров памяти . Синхронизация потоков в основном состоит из двух частей: сериализации и видимости. Я советую всем использовать Google для «барьера памяти jvm», так как это нетривиальная и чрезвычайно важная тема (если вы изменяете общие данные, к которым обращаются несколько потоков). Сделав это, я советую взглянуть на классы пакета java.util.concurrent, которые помогают избежать использования явной синхронизации, что, в свою очередь, помогает сделать программы простыми и эффективными, возможно, даже предотвращает взаимные блокировки.
Одним из таких примеров является ConcurrentLinkedDeque . Вместе с шаблоном команд он позволяет создавать высокоэффективные рабочие потоки, помещая команды в параллельную очередь - не требуется явная синхронизация, невозможны взаимоблокировки, не требуется явный сон (), просто опросите очередь, вызвав take ().
Вкратце: «синхронизация памяти» происходит неявно, когда вы запускаете поток, поток заканчивается, вы читаете энергозависимую переменную, вы разблокируете монитор (оставляете синхронизированный блок / функцию) и т. Д. Эта «синхронизация» влияет (в некотором смысле «сбрасывает» ") все записи сделаны до этого конкретного действия. В случае вышеупомянутого ConcurrentLinkedDeque документация «говорит»:
Это неявное поведение является несколько пагубным аспектом, потому что большинство Java-программистов без особого опыта просто примут многое из-за этого. А потом неожиданно наткнулся на этот поток после того, как Java не выполняет то, что «предполагается» делать в рабочей среде, где существует другая рабочая нагрузка - и довольно сложно протестировать проблемы параллелизма.
источник
Синхронизированный означает просто, что несколько потоков, если они связаны с одним объектом, могут предотвратить грязное чтение и запись, если синхронизированный блок используется для определенного объекта. Чтобы дать вам больше ясности, давайте возьмем пример:
Мы создали два объекта класса MyRunnable: runnable1 совместно используется с потоком 1, а поток 3 и runnable2 - только с потоком 2. Теперь, когда t1 и t3 запускаются без использования синхронизации, вывод PFB предполагает, что оба потока 1 и 3 одновременно влияют на значение var, где для потока 2 var имеет свою собственную память.
Используя Synchronzied, поток 3 ожидает завершения потока 1 во всех сценариях. Получены две блокировки: одна для runnable1, совместно используемая потоком 1 и потоком 3, а другая для runnable2, совместно используемая потоком 2.
источник
простая синхронизация означает, что никакие два потока не могут получить доступ к блоку / методу одновременно. Когда мы говорим, что любой блок / метод класса синхронизирован, это означает, что только один поток может получить к ним доступ одновременно. Внутренне поток, который пытается получить к нему доступ, сначала блокирует этот объект, и пока эта блокировка недоступна, никакой другой поток не может получить доступ ни к одному из синхронизированных методов / блоков этого экземпляра класса.
Обратите внимание, что другой поток может получить доступ к методу того же объекта, который не определен для синхронизации. Поток может снять блокировку, вызвав
источник
synchronized
Блок в Java - это монитор в многопоточности.synchronized
Блок с тем же объектом / классом может быть выполнен только одним потоком, все остальные ожидают. Это может помочь вrace condition
ситуации, когда несколько потоков пытаются обновить одну и ту же переменную (первый шаг - использованиеvolatile
About )Java 5
продленsynchronized
путем поддержкиhappens-before
[О]Следующий шаг
java.util.concurrent
энергозависимый и синхронизированный
источник
синхронизированный - это ключевое слово в Java, которое используется для того, чтобы происходило до взаимосвязи в среде многопоточности, чтобы избежать несогласованности памяти и ошибки вмешательства потока.
источник