хорошо известный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, и заинтересованные друзья могут поддерживать их вместе.