2010-05-24 5 views
15

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

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

Пример:

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

ReentrantLock lock = new ReentrantLock(); 

Тема 1 пробеги:

synchronized (lock) { 
    // blah 
} 

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

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

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

ответ

14

Нет, Резьба 2 может lock(), даже если Thread 1 is synchronized на том же lock. Это то, что documentation должен сказать:

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

+0

Вот что я понял. Там есть одно место, где мне нужно использовать 'ReetrantLock.tryLock()', и я надеялся уйти с 'synchronized' везде. Благодарю. –

9

Два механизма разные. Реализация/эффективность:

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

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

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

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

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

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

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

Смежные вопросы