Подробное объяснение оптимизации блокировки JVM и анализа выхода

JVM
Подробное объяснение оптимизации блокировки JVM и анализа выхода

«Это пятый день моего участия в первом испытании обновлений 2022 года. Подробную информацию о мероприятии см.:Вызов первого обновления 2022 г.".

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

В процессе блокировки jvm будет использовать такие методы оптимизации, как спин, самоадаптация, устранение блокировок и огрубление блокировок, чтобы повысить эффективность выполнения кода.

Спин-блокировки и адаптивный спин

Большинство процессоров в настоящее время являются многоядерными процессорами.Если на многоядерном процессоре параллельно выполняются два или более потока, мы можем позволить ожидающему потоку не уступать время выполнения процессора. Установите тайм-аут ожидания, чтобы увидеть, может ли поток быстро снять блокировку.В течение периода ожидания можно выполнить пустой цикл, чтобы текущий поток продолжал занимать квант времени ЦП. Это называетсяблокировка спина.

в JVM через+XX:UseSpinningЧтобы включить блокировку вращения, она у нас включена по умолчанию после JDK1.6. Поскольку использование спин-блокировок может привести к тому, что конкуренты по блокировкам будут занимать больше процессорного времени, JVM задает параметр для количества спинов. мы можем пройти-XX:PreBlockSpingвнести изменения (по умолчанию 10 раз).

Переходы состояний смещенных блокировок, облегченных блокировок и отношения объекта Mark Word преобразуются, как показано на следующем рисунке:偏向锁、轻量级锁的状态转化及对象 Mark Word 的关系

снятие блокировки

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

Ниже приведен пример добавления трех строк x, y, z, не являющихся ни исходным кодом, ни логически синхронизированным.

public String concatStr(String x, String y, String z) {
    return  x + y + z;
}

String является неизменяемым классом, и связывание символов всегда генерирует новый объект String, поэтому компилятор Javac автоматически оптимизирует связывание строк.До jdk5 связывание строк было преобразовано вStringBuffer; после того, как jdk5 будет преобразован вStringBuilderобъект непрерывныйappend()Operation, посмотрим на результат декомпиляции после javac:

public String concatStr(String x, String y, String z) {
    StringBuilder sb = new StringBuilder();
    sb.append(x);
    sb.append(y);
    sb.append(z);
    return  sb.toString();
}

Посмотрим еще разjavapДекомпилированный результат:image.pngВы можете беспокоиться здесьStringBuilderСуществуют ли проблемы с потокобезопасностью для операций, которые не являются потокобезопасными? Ответ здесь нет,x + y + zОптимизация работыПосле анализа побегаПосле этого его динамический диапазон ограничиваетсяconcatStrВ методе, то есть текущем фактическом выполненииStringBuilderоперация вconcatStrвнутри метода,Другие внешние потоки не могут получить доступ

StringBuffer buffer = new StringBuffer();
/**  锁粗化 */ 
public void append(){ 
	buffer.append("aaa").append(" bbb").append(" ccc"); 
}