13 апреля 2011 г.

ReentrantLock vs synchronized

Загадочное поведение старых и новых локов в java (регулярно обнаруживаю паттерны, где ReentrantLock быстрее, и так же регулярно -- где выигрывает synchronized) -- наконец-то получило более-менее вменяемое объяснение. Сегодня, на Java One мне рассказали всю правду о том, как и какие локи устроены.

Вкратце, ответ на мой вопрос такой: при малом уровне contention выигрывает synchronized, при большом -- ReentrantLock. synchronized выигрывает за счет того, что для него работает "привязывание" (biased locking) -- для Reentrant такая оптимизация пока не реализована. Reentrant выигрывает за счет того, что для него (в non-fair режиме) реализовано "выхватывание" (bargain) блокировки, когда поток, подошедший на блокировку точно в момент, когда ее освободил другой поток, получит блокировку немедленно, в обход уже, может быть, целой очереди давно ждущих этой блокировки потоков. Это, хотя и "не честно", зато позволяет сэкономить на переключении контекстов потоков.

Никто, разумеется, не отменял бенчмарков в конкретном приложении...

2 комментария:

  1. Я даже больше скажу: реализация схемы biased locking'а в ReentrantLock потребует такого геморроя со стороны VM (надо остановить владельца), что проще его не делать, а надеяться на barging дешёвым локальным CAS'ом. Хотя там всё равно барьер остаётся.

    ОтветитьУдалить
  2. Ю

    С той реализацией, что рассказывал мне Сергей -- да, представляю себе :) Но вот здесь http://cheremin.blogspot.com/www.trl.ibm.com/people/kawatiya/Kawachiya05phd.pdf (ближе к концу) после этой версии реализации привязывания (которая с перемещением IP, и всякими низкоуровневыми хаками) описана другая реализация, которая не требует ничего кроме CAS, и вдобавок позволяет довольно недорогой rebiasing... Я как бы не большой спец в этом -- что скажете?

    ОтветитьУдалить