Смешивание synchronized () с ReentrantLock.lock () - PullRequest
15 голосов
/ 25 мая 2010

В Java ReentrantLock.lock() и ReetrantLock.unlock() используют тот же механизм блокировки, что и synchronized()?

Мое предположение "Нет", но я надеюсь, что ошибаюсь.

Пример:

Представьте, что поток 1 и поток 2 имеют доступ к:

ReentrantLock lock = new ReentrantLock();

Тема 1 запускается:

synchronized (lock) {
    // blah
}

Тема 2 работает:

lock.lock();
try {
    // blah
}
finally {
    lock.unlock();
}

Предположим, что поток 1 сначала достигнет своей части, а затем поток 2, прежде чем поток 1 будет завершен: будет ли поток 2 ждать, пока поток 1 покинет блок synchronized(), или он продолжит работу и будет работать?

Ответы [ 3 ]

14 голосов
/ 25 мая 2010

Нет, поток 2 может lock(), даже если поток 1 synchronized на том же lock. Вот что говорит документация :

Обратите внимание, что экземпляры Lock просто нормальные объекты и сами могут быть используется в качестве цели в синхронизированном заявление. Получение блокировки монитора экземпляра Lock не указан отношения с использованием любого из методы lock () этого экземпляра. Это рекомендуется, чтобы избежать путаницы Вы никогда не используете экземпляры Lock в этом Кстати, кроме как в пределах своей осуществление.

9 голосов
/ 25 мая 2010

Два механизма разные. Внедрение / производительность в отношении:

  • синхронизированный механизм использует механизм блокировки, который «встроен» в JVM; базовый механизм зависит от конкретной реализации JVM, но обычно использует комбинацию необработанной команды сравнения и установки (CAS) для случаев, когда блокировка не оспаривается, плюс базовые механизмы блокировки, предоставляемые ОС;
  • классы блокировки, такие как ReentrantLock, в основном кодируются на чистой Java (через библиотеку, представленную в Java 5, которая предоставляет инструкции CAS и планирование потоков в Java), и поэтому они несколько более стандартизированы в ОС и более управляемы (см. Ниже).

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

(Я должен также сказать, что производительность синхронизированной была улучшена в более поздних версиях Hotspot; в последних версиях ее может не быть много или даже при других обстоятельствах - это, очевидно, один тест в одной среде. )

Функционально:

  • синхронизированный механизм обеспечивает минимальную функциональность (вы можете блокировать и разблокировать, блокировка - это операция «все или ничего», вы в большей степени подчинены алгоритму, выбранному разработчиками ОС), хотя и с преимуществом встроенного синтаксиса и некоторый мониторинг, встроенный в JVM;
  • классы явной блокировки предоставляют больше контроля, в частности, вы можете указать «справедливую» блокировку, блокировку с тайм-аутом, переопределение, если вам нужно изменить текущую позицию блокировки ...
0 голосов
/ 04 мая 2011

Почему баланс статичен в классе Account? Уберите статический и он должен работать.

Кроме того, есть вопрос об использовании вашей темы. В вашем TestMain вы создаете новые потоки и назначаете такие исполняемые объекты, как WithdrawRequests & DepositRequests. Но опять же вы создаете новые потоки внутри конструкторов этих runnables. Это приведет к тому, что метод run будет выполнен дважды!

...