Принцип синхронизации ключевых слов

интервью Java задняя часть Безопасность

хорошо известныйSynchronizeКлючевые слова часто используются для решения проблем параллелизма. Есть три способа их использования:

  • Синхронизированный обычный метод, блокировкой является текущий объект.
  • Синхронный статический метод, замок токаClassобъект.
  • Синхронизированный блок, блокировка есть{}объект в .

Принцип реализации:JVMвходя и выходя из монитора объектов (Monitor) для достижения синхронизации методов и блоков синхронизации.

Конкретная реализация заключается в добавленииmonitor.enterИнструкции, вставленные при выходе из методов и исключенийmonitor.exitинструкция.

Суть его в наблюдении за объектом (Monitor) для получения, и этот процесс получения является эксклюзивным, так что только один поток может получить к нему доступ в каждый момент времени.

Для потока, который не получает блокировку, он будет блокироваться на входе в метод до тех пор, пока поток, который не получит блокировкуmonitor.exitТолько после этого можно предпринимать дальнейшие попытки получить блокировку.

Блок-схема выглядит следующим образом:

Чтобы продемонстрировать фрагмент кода:

    public static void main(String[] args) {
        synchronized (Synchronize.class){
            System.out.println("Synchronize");
        }
    }

использоватьjavap -c SynchronizeВы можете просмотреть конкретную информацию после компиляции.

public class com.crossoverjie.synchronize.Synchronize {
  public com.crossoverjie.synchronize.Synchronize();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // class com/crossoverjie/synchronize/Synchronize
       2: dup
       3: astore_1
       **4: monitorenter**
       5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       8: ldc           #4                  // String Synchronize
      10: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      13: aload_1
      **14: monitorexit**
      15: goto          23
      18: astore_2
      19: aload_1
      20: monitorexit
      21: aload_2
      22: athrow
      23: return
    Exception table:
       from    to  target type
           5    15    18   any
          18    21    18   any
}

Видно, что вход и выход синхронизированного блока имеютmonitorenter,monitorexitинструкция.

оптимизация блокировки

synchronizeМногие называют это замком веса,JDK1.6средняя параsynchronizeВнесены различные оптимизации, чтобы уменьшить потребление блокировок и снятие блокировок.偏向锁и轻量锁.

Легкий замок

Когда код входит в синхронизированный блок, если объект синхронизации свободен от блокировки, текущий поток создает запись блокировки в кадре стека (Lock Record) при размещении объекта блокировки в заголовке объектаMark WordСкопируйте его в запись блокировки и повторите попытку.CASбудетMark WordОбновите указатель на запись блокировки.

если обновленоуспех, текущий поток получает блокировку.

если обновленоПотерпеть поражение JVMОбъект блокировки будет проверен первымMark WordЧтобы указывать на запись блокировки текущего потока.

Если это так, это означает, что текущий поток владеет блокировкой объекта блокировки и может напрямую войти в блок синхронизации.

Если нет, это означает, что другие потоки захватили блокировку.Если за блокировку одновременно борются несколько потоков,Легкие замки превращаются в тяжелые замки.

разблокировать

Процесс разблокировки легкого замка также используетCASДля этого он попытается заменить запись блокировки записью блокировки.Mark Word. Если замена прошла успешно, это означает, что вся операция синхронизации завершена, если нет, то это означает, что другие потоки пытаются получить блокировку, а приостановленный поток в это время будет разбужен.重量锁)

Причина, по которой упрощенные блокировки могут повысить производительность, заключается в том, что большинство блокировок не конкурируют друг с другом в течение всего цикла синхронизации, поэтому используйтеCASМеньше накладных расходов, чем при использовании мьютекса. Но если конкуренция замков жесткая, облегченный замок не только несет накладные расходы на взаимное исключение, но иCASНакладные расходы даже медленнее, чем весовые замки.

Блокировка смещения

Для дальнейшего снижения стоимости приобретения замков,JDK1.6Замки смещения также были введены позже.

Характеристики смещенных блокировок: нет многопоточной конкуренции за блокировку, и поток должен получать блокировку несколько раз.

Когда поток обращается к синхронизированному блоку, он используетсяCASОбновите идентификатор потока до объекта блокировки.Mark Word, Если обновление успешно, представляет собой предвзятый замок, и каждый раз он входит в блок синхронизации, связанный с блокировкой объекта, ему не нужно снова получать блокировку.

разблокировать замок

Когда другой поток получает блокировку, поток, удерживающий блокировку смещения, снимет блокировку, дождется глобальной точки сохранения (в этот момент байт-код не выполняется), а затем приостановит поток, удерживающий блокировку смещения, в соответствии с блокировкой. в настоящее время заблокирован, используется для определения того,Mark WordУстановите в состояние без блокировки или легкой блокировки.

Облегченная блокировка может повысить производительность программ с синхронизацией, но без конкуренции, но если большинство блокировок в программе являются конфликтными, то предвзятая блокировка мало что даст. можно использовать-XX:-userBiasedLocking=falseчтобы отключить блокировку смещения и ввести блокировку света по умолчанию.

Другие оптимизации

адаптивный спин

в настоящее время используетCAS, если операция не удалась,CASБудет вращаться, чтобы попробовать еще раз. Поскольку вращение потребляетсяCPUресурсов, так что если долго крутить, то будет впустуюCPU.JDK1.6Добавлен адаптивный спин:

Если блокировка спина редко бывает удачной, то в следующий раз спин будет уменьшен.

Дополнительный

Недавно я обобщил некоторые знания, связанные с Java, и заинтересованные друзья могут поддерживать их вместе.

адрес:GitHub.com/crossover J я…