синхронизированный и повторный зал
В многопоточном программировании мы используем блокировки, когда код должен быть синхронизирован. Java предоставляет нам два метода синхронизации: встроенный блокировка (синхронизированный) и явный блокировка (Reentrantlock). Явные замки были введены JDK1.5. Каковы сходства и различия между этими двумя замками? Это просто вариант или есть еще одна причина? Эта статья узнает для вас.
// Пример синхронизированного использования ключевых слов Публичный синхронизированный void add (int t) {// Синхронизированный метод this.v += t;} public static void sub (int t) {// Синхронизированное статическое значение -= t;} public int descementAndget () {synchronized (obj) {// синхронизированный код возврат; }}Это все о использовании встроенных замков, вы узнали об этом.
Встроенный замок очень удобен в использовании и не требует явного сбора и выпуска. Любой объект может быть использован в качестве встроенного замка. Использование встроенных замков может решить большинство сценариев синхронизации. «Любой объект может быть использован в качестве встроенной блокировки» также означает, что там, где появляется синхронизированное ключевое слово, с ним связан объект. Конкретно:
При синхронизированных действиях на нормальном методе объект блокировки это;
При синхронизированных действиях на статическом методе объект блокировки является объектом класса текущего класса;
При синхронизированных действиях в кодовом блоке объект блокировки является синхронизированным (OBJ).
Явный блокировка
Встроенный замок так прост в использовании, почему вам нужен дополнительный явный блокировка? Потому что некоторые вещи не могут быть сделаны со встроенными замками, такими как:
Мы хотим добавить время ожидания в замок и сдаться до получения тайм -аута, чтобы мы не будем ждать бесконечно;
Мы хотим приобрести блокировку прерывистым способом, чтобы внешний поток посылал нам сигнал прерывания и может вызвать поток, ожидающий блокировки;
Мы хотим поддерживать несколько очередей ожидания для замков, таких как очередь производителей и очередь потребителей, одновременно повышая эффективность замков.
Явные замки (повторные блоки) официально рождены для решения этих гибких потребностей. Reentrantlock буквально означает reentrant Lock, а Reentrant означает, что поток может запрашивать один и тот же блокировку несколько раз одновременно, не вызывая его само по себе. Вот разница между встроенным замком и явным замком:
Timileable: Renentrantlock.trylock (Long Timeout, TimeUnit Unit) предоставляет способ закончить время ожидания. Если поток не получает блокировку в течение указанного времени, метод вернет FALSE и завершит ожидание потока.
Прерывище: вы, должно быть, видели прерванное. Многие многопоточные методы вызовут это исключение. Это исключение - не бремя, вызванное дефектом, а необходимостью или хорошей вещью. Беретчивость дает нам способ получить поток рано (вместо того, чтобы ждать, пока не закончится выполнение потока), что очень полезно для трудоемких задач. Для встроенных замков нить будет ждать встроенного блокировки, если он не сможет получить его. Нет другого способа закончить ожидание, кроме как приобрести замок. Renentrantlock.lockEntertible () дает нам возможность закончить ожидание прерыванием.
Очередь состояния: после получения потока заблокирован, он может ввести состояние ожидания, поскольку он ожидает определенного условия (встроенная блокировка проходит через метод object.wait (), а явная блокировка проходит через метод Condity.await ()). Поток, попадающий в состояние ожидания, будет висеть и автоматически отпустить блокировку, и эти потоки будут помещены в очередь состояния. Синхронизированный имеет только одну условную очередь, в то время как reentrantlock может иметь несколько условных очередей. Каковы преимущества нескольких очередей? Пожалуйста, прочитайте.
Условный предикат: после того, как нить приобретает блокировку, иногда ему нужно ждать, пока определенное условие будет выполнено, прежде чем он сможет что -то сделать. Например, производитель должен подождать, пока кэш не будет удовлетворен, прежде чем он сможет поместить сообщения в очередь, в то время как потребитель должен ждать, пока кэш не будет пустым, прежде чем он сможет извлечь сообщения из очереди. Эти условия называются условными предикатами. Поток должен сначала получить блокировку, а затем определить, выполняется ли условный предикат. Если это не удовлетворено, это не будет выполнено вниз. Соответствующий поток отказатся от правого выполнения и автоматически отпустит блокировку. Различные потоки с использованием одной и той же блокировки могут иметь разные условные предикаты. Если существует только одна условная очередь, когда условное предикат выполняется, невозможно определить, какой поток в условной очереди проснуться; Но если каждый условный предикат имеет отдельную условную очередь, когда условное выполняется, мы знаем, что поток на соответствующей очереди следует пробудить (встроенный блокировка пробуждается через объект. Неоткрытие () или объект. Это преимущество нескольких условных очередей.
При использовании встроенных замков сам объект является как блокировкой, так и условной очередью; При использовании явных замков объект RenentRantlock представляет собой блокировку, а условная очередь получается через метод RenentRantlock.newCondition (). Несколько условных очередей можно получить, вызывая этот метод несколько раз.
Типичный пример использования явного блокировки заключается в следующем:
// Пример использования явного блокировки reentrantlock lock = new Reentrantlock (); // Приобретение блокировки, это использование, соответствующее ключевому слову синхронизированного. lock.lock (); try {// your Code} наконец {lock.unlock ();} // Вы можете время и отказаться от блокировки, если вы получите блокировку после превышения указанного времени. try {lock.trylock (10, timeUnit.seconds); попробуйте {// ваш код} наконец {lock.unlock (); }} catch (прерывание E1) {// Обработка исключений} // Вы можете прервать, и поток потока может быть прерван при ожидании получения блокировки try {lock.lockintertible (); попробуйте {// ваш код} наконец {lock.unlock (); }} catch (прерывание Exception e) {// Обработка исключений} // Многочисленные очереди ожидания, пожалуйста, см. Ожидание ставит */частное окончательное условие natfull = lock.newcondition ();Обратите внимание, что приведенный выше код помещает разблокировку () в блоке, что необходимо. Явная блокировка не будет автоматически выпущена, как встроенная блокировка. При использовании явного блокировки его нужно вручную выпустить в блоке, наконец,. Если блокировка не будет выпущена из -за исключения после получения блокировки, то замок никогда не будет выпущен! Поместите Unlock () в Block, чтобы убедиться, что он может быть выпущен нормально, независимо от того, что происходит.
в заключение
Встроенные замки могут решать большинство сценариев, которые требуют синхронизации. Только когда требуется дополнительная гибкость, необходимо учитывать явные блокировки, такие как время, прерываемая и несколько очередей ожидания.
Хотя явные блокировки являются гибкими, они требуют явного применения и выпуска, а выпуск должен быть помещен в наконец -то блок, в противном случае блокировка никогда не может быть выпущена из -за исключений! Это самый очевидный недостаток явного блокировки.
Таким образом, при синхронизации, пожалуйста, отдайте приоритет более безопасным и проще в использовании неявных замков.