Издержки нескольких синхронизированных на одном объекте - PullRequest
0 голосов
/ 15 ноября 2018

Рассмотрим этот код:

void A() {
    synchronized (obj) {
        for (int i = 0; i < 1000; i++) {
            B();
        }
    }
}

void B() {
    synchronized (obj) {
        // Do something
    }
}

Сколько будет стоить «синхронизация» при вызове A?Это будет близко к накладным расходам только одной "синхронизированной"?

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

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

Если оставить в стороне стоимость вызова функции, она может почти ничего не стоить в одной ОС / архитектуре (рассмотрим современный процессор / ОС / ВМ) и намного больше в другой (рассмотрим чисто программную эмуляцию процессора). На одной виртуальной машине с зеленым потоком она может стоить около нуля (кроме затрат на вызов). Стоимость будет отличаться даже между ARM и Intel сопоставимой мощности.

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

На современных виртуальных машинах Windows / Linux и процессорах Intel / AMD, как правило, он не стоит больших циклов ЦП (при условии простоя компьютера) и находится в диапазоне низких наносекунд.

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

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

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

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

0 голосов
/ 15 ноября 2018

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

Первый занимает самое длинное время и прибавляет около 10 - 50 нс каждый раз.

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