Смешение синхронизированного() с ReentrantLock.lock()
В Java, do ReentrantLock.lock()
и ReetrantLock.unlock()
используют тот же механизм блокировки, что и synchronized()
?
Мое предположение: "Нет", но я надеюсь ошибиться.
Пример:
Представьте, что в Thread 1 и Thread 2 есть доступ к:
ReentrantLock lock = new ReentrantLock();
Тема 1:
synchronized (lock) {
// blah
}
Режимы Thread 2:
lock.lock();
try {
// blah
}
finally {
lock.unlock();
}
Предположим, что Thread 1 сначала достигнет своей части, затем Thread 2 до завершения Thread 1: будет ли Thread 2 ждать, пока Thread 1 покинет блок synchronized()
, или он продолжит работу и запустится?
Ответы
Ответ 1
Нет, Thread 2 может lock()
, даже если Thread 1 является synchronized
на том же lock
. Это то, что документация должна сказать:
Обратите внимание, что экземпляры блокировки просто нормальные объекты и могут сами быть используется как цель в синхронизированном выражение. Приобретение блокировки монитора экземпляра блокировки не указано отношения с вызовом любого из lock() этого экземпляра. Это рекомендуется избегать путаницы вы никогда не используете экземпляры блокировки в этом способом, за исключением собственных реализация.
Ответ 2
Два механизма различны. Реализация/производительность:
- синхронизированный механизм использует механизм блокировки, который "встроен в" JVM; основной механизм зависит от конкретной реализации JVM, но обычно использует комбинацию необработанной команды сравнение и настройка (CAS) для случаев где блокировка не поддерживается, плюс основные механизмы блокировки, предоставляемые ОС;
- классы блокировки, такие как ReentrantLock, в основном закодированы в чистой Java (через библиотеку, представленную на Java 5, которая предоставляет инструкции CAS и дескремирование потоков на Java), и поэтому несколько более стандартизирована в ОС и более контролируема (см. ниже).
В некоторых случаях явные блокировки могут работать лучше. Если вы посмотрите на это сравнение механизмов блокировки, я выполнил в Java 5, вы увидите, что в этом конкретном тесте (несколько потоков, обращающихся к массиву), явные классы блокировок, настроенные в режиме "несправедливости" (желтый и голубой треугольники), обеспечивают большую пропускную способность, чем простая синхронизация (пурпурные стрелки).
(Я должен также сказать, что производительность синхронизации была улучшена в более поздних версиях Hotspot, в ней может быть не так много в последних версиях или даже при других обстоятельствах - это, очевидно, один тест в одной среде. )
Функционально:
- синхронизированный механизм обеспечивает минимальную функциональность (вы можете блокировать и разблокировать, блокировка - это операция "все или ничего", вы более подвержены алгоритму, который были определены авторами ОС), хотя с преимуществом встроенного синтаксиса и некоторый мониторинг, встроенный в JVM;
- явные классы блокировки обеспечивают больше контроля, особенно вы можете указать "честную" блокировку, блокировку с таймаутом, переопределить, если вам нужно изменить функцию блокировки...
Ответ 3
Почему вы сделали статичность баланса в классе Account?
Удалите статику, и она должна работать.
Кроме того, задайте вопрос об использовании потока. В TestMain вы создаете новые потоки и назначаете runnables, такие как WithdrawRequests и DepositRequests. Но снова вы создаете новые потоки внутри конструкторов этих runnables. Это приведет к тому, что метод запуска будет выполнен дважды!