Многопоточность synchronized

190
07 августа 2018, 03:00

На сколько мне известно ключевое слово synchronize, в десятки если не сотни раз замедляет выполнение метода, чем обусловлен такой колоссальный проигрыш в скорости, и есть ли какие-либо аналоги синхронизации потоков?

Answer 1

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

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

Answer 2

Как уже заметили авторы других ответов, основная причина замедления в том, что синхронизированный метод/блок может выполнять только один поток за раз, а другим приходиться ждать. Но есть и другие факторы, который вносят куда меньший вклад в замедление, но всё же могут быть заметны в алгоритмах с высокими требованиями к производительности. Первый такой фактор - это накладные расходы на операции захвата/освобождения монитора. Для biased монитора они минимальны - укладываются в несколько аппаратных инструкций, но при высоком contention виртуальной машине приходится выполнять существенно больше действий. В том числе действий с участием системных вызовов, что приводит к переключению контекста. Второй фактор - это safepoint'ы. В случае HotSpot они могут быть только глобальными, поэтому раздувание/сдувание монитора на мгновение останавливает абсолютно все потоки JVM, включая сервисные. Третий фактор, ещё более низкоуровневый - это необходимость использовать memory barrier при захвате монитора. Это снижает возможности по оптимизации reordering'ом и заставляет процессоры заниматься синхронизацией кэш-памяти.

Поэтому при написании многопоточных программ так важно по максимуму снизить использование разделённого состояния или сделать его неизменяемым. Immutability и confinement - лучшие альтернативы синхронизации.

Answer 3

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

Чем дольше выполняется блок кода, доступ к которому потоки должны получать по очереди, тем хуже. НО если это действительно такой код, с которым нельзя работать одновременно с нескольких потоков, то иного выхода нет. Надо синхронизировать. Ключевое слово synchronize это просто удобный инструмент от Java. Если очень много подобного кода, то лучше использовать более гибкие инструменты. Интерфейсы Lock и Condition были добавлены в Java SE 5.0, чтобы предоставить программистам высокую степень контроля блокировок.
Так же в Java есть ключевое слово volatile , которое разрешает с переменной работать одновременно одному потоку. О некоторых подводных камнях можно прочитать здесь И так же хорошая статья из которой можно понять о том как всё это работает.

Слово synchronized в Java "на пальцах"

Думаю должно быть понятно, что если это сервер к которому обращаются тысячи клиентов и есть некий элемент, который нельзя менять одновременно нескольким клиентам, то придется становиться в очередь. То же самое, если это приложение, в котором к блоку кода обращаются, например, 8 потоков. Блок кода, допустим выполняется за 1 сек. Все потоки вместо пройдут его чуть больше, чем за 8 сек. Это конечно такое не точное объяснение, но этого пока достаточно. Просто стоит знать, что если нужна синхронизация , то это либо использование synchronize, которое оставит код читабельнее, но воздействует глобально, возможно, и на участки кода, где синхронизация не нужна. Либо использовать другие инструменты для точечного воздействия.

READ ALSO
Русские символы для FileInputStream

Русские символы для FileInputStream

у меня есть интерфейс а в нем метод

200
Замена специальных символом на числа по порядку

Замена специальных символом на числа по порядку

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

183
Android Fragment, передача ссылки в браузер

Android Fragment, передача ссылки в браузер

Имеется ссылка, которую необходимо открыть в браузереКак это можно сделать? У Activity - intentом, а у фрагментов как?

169
Получение ссылки на объект Class класса String [закрыт]

Получение ссылки на объект Class класса String [закрыт]

Есть следующее тестовое задание:

202