На сколько мне известно ключевое слово synchronize
, в десятки если не сотни раз замедляет выполнение метода, чем обусловлен такой колоссальный проигрыш в скорости, и есть ли какие-либо аналоги синхронизации потоков?
Проигрыш возникает только в многопоточной среде, на одном потоке разницы нет. Дело в том, что для выполнения synchronized
блока, все потоки должны дойти до места его начала, а далее по очереди выполнить synchronized
блок на одном потоке.
Однозначно ответить на вопрос про аналоги синхронизации не получится, вопрос слишком общий и в зависимости от данных и реализации сильно варьируется, есть блокирующие алгоритмы, есть неблокирующие, транзакционная память. В данном случае уже надо разбираться в конкретной задаче, представлении данных и способе их обработки, в идеале все данные должны обрабатываться независимо, тогда и синхронизировать потоки не потребуется.
Как уже заметили авторы других ответов, основная причина замедления в том, что синхронизированный метод/блок может выполнять только один поток за раз, а другим приходиться ждать. Но есть и другие факторы, который вносят куда меньший вклад в замедление, но всё же могут быть заметны в алгоритмах с высокими требованиями к производительности. Первый такой фактор - это накладные расходы на операции захвата/освобождения монитора. Для biased монитора они минимальны - укладываются в несколько аппаратных инструкций, но при высоком contention виртуальной машине приходится выполнять существенно больше действий. В том числе действий с участием системных вызовов, что приводит к переключению контекста. Второй фактор - это safepoint'ы. В случае HotSpot они могут быть только глобальными, поэтому раздувание/сдувание монитора на мгновение останавливает абсолютно все потоки JVM, включая сервисные. Третий фактор, ещё более низкоуровневый - это необходимость использовать memory barrier при захвате монитора. Это снижает возможности по оптимизации reordering'ом и заставляет процессоры заниматься синхронизацией кэш-памяти.
Поэтому при написании многопоточных программ так важно по максимуму снизить использование разделённого состояния или сделать его неизменяемым. Immutability и confinement - лучшие альтернативы синхронизации.
Блокировка защищает сегмент кода, позволяя только одному потоку в единицу времени выполнять этот код.
Блокировка управляет потоками, которые пытаются войти в защищенный сегмент кода.
Каждый объект условия управляет потоками, вошедшими в защищенный сегмент кода, но которые пока не в состоянии выполнять работу.
Чем дольше выполняется блок кода, доступ к которому потоки должны получать по очереди, тем хуже. НО если это действительно такой код, с которым нельзя работать одновременно с нескольких потоков, то иного выхода нет. Надо синхронизировать. Ключевое слово synchronize
это просто удобный инструмент от Java. Если очень много подобного кода, то лучше использовать более гибкие инструменты.
Интерфейсы Lock
и Condition
были добавлены в Java SE 5.0, чтобы предоставить программистам высокую степень контроля блокировок.
Так же в Java есть ключевое слово volatile
, которое разрешает с переменной работать одновременно одному потоку.
О некоторых подводных камнях можно прочитать здесь И так же хорошая статья из которой можно понять о том как всё это работает.
Слово synchronized в Java "на пальцах"
Думаю должно быть понятно, что если это сервер к которому обращаются тысячи клиентов и есть некий элемент, который нельзя менять одновременно нескольким клиентам, то придется становиться в очередь. То же самое, если это приложение, в котором к блоку кода обращаются, например, 8 потоков. Блок кода, допустим выполняется за 1 сек. Все потоки вместо пройдут его чуть больше, чем за 8 сек. Это конечно такое не точное объяснение, но этого пока достаточно. Просто стоит знать, что если нужна синхронизация , то это либо использование synchronize
, которое оставит код читабельнее, но воздействует глобально, возможно, и на участки кода, где синхронизация не нужна. Либо использовать другие инструменты для точечного воздействия.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Необходим кусочек кода, который позволит заменять специальные символы на числа, которые будут идти по порядку
Имеется ссылка, которую необходимо открыть в браузереКак это можно сделать? У Activity - intentом, а у фрагментов как?