Стоимость синхронизации

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

void synchronized something() {
     ...
}

или

void something() {
     synchronized(this) {
         ...
     }
     // here do stuff no requiring synchronization
     .
     . // do computation 'A'
     .
     synchronized(this) {
         ...
     }
     // here do other stuff no requiring synchronization
     .
     . // do computation 'B'
     .
     synchronized(this) {
         ...
     }
}

Теперь я понимаю, что если вычисление "A" и "B" занимает много времени, вторая версия, очевидно, лучше.

Однако мой вопрос: в какой момент вы знаете, что вторая версия более эффективна?

Является ли вторая версия всегда быстрее или есть скрытая стоимость приобретения/освобождения блокировки несколько раз?

Что делать, если мои вычисления "А" просто тривиальны:

s.getString().substring( 0, 2 ).toLowerCase();

Ответ 1

Да, synchronized стоит время. Если фактические вычисления просты и находятся внутри цикла или около того, это стоит лотов времени по сравнению с фактическими вычислениями.

Смотрите этот пример: http://ideone.com/zgpB7

  • Внутренняя часть синхронизирована: приблизительно 0.025s
  • Синхронизация всей петли: менее 0,001 с

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

Ответ 2

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

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

Ответ 3

"Правильно ли написано" и "правильно синхронизировано" означает, что между разделами кода в многосинхронизированном случае нет зависимостей? Если есть зависимости, то может быть, что многосинхронизированный случай может привести к нарушению инварианта. Иными словами, можете ли вы гарантировать, что выполнение многосинхронизированного случая не приведет к тому, что какой-либо объект окажется в недопустимом состоянии? Если нет, то односинхронизированный случай может быть лучше.