Чтобы узнать больше интересного контента заранее, пожалуйста, посетителичный блог Чтобы узнать больше интересного контента заранее, пожалуйста, посетителичный блог Чтобы узнать больше интересного контента заранее, пожалуйста, посетителичный блог
написать впереди
существуетНаглядность и упорядоченность, Бывает-прежде чем это сделатьВ статье один из принципов случая-раньше: правило volatile-переменной
Запись в энергозависимый домен происходит до чтения энергозависимого домена в любом последующем
Само собой разумеется, что если вы понимаете это правило, использования volatile достаточно, но интервьюер любит докапываться до сути. несколько лишних баллов за интервью пункт, а заодно заполнить дыру оставленную предыдущей статьей как можно скорее, поэтому эта статья родилась таким неловким образом
правила «происходит до» для volatile-переменных
Вы помните форму ниже? (да, ты помнишь 😂)
Можно ли переупорядочить | вторая операция | вторая операция | вторая операция |
---|---|---|---|
первое действие | Обычное чтение/запись | изменчивое чтение | изменчивая запись |
Обычное чтение/запись | - | - | NO |
изменчивое чтение | NO | NO | NO |
изменчивая запись | - | NO | NO |
上面的表格是 JMM 针对编译器定制的 volatile 重排序的规则,那 JMM 是怎样禁止重排序的呢? ответбарьер памяти
Барьеры памяти / Заборы
Неважно, слышали вы этот термин или нет, он прост, и вы увидите
Чтобы достичь семантики памяти volatile, компилятор вставляет барьеры памяти в последовательность инструкций, чтобы запретить определенные типы переупорядочения процессора при генерации байт-кода.
Это предложение немного абстрактно, попробуйте представить, что барьер памяти — это высокая стена, если между двумя переменными есть этот барьер, то они не могут поменяться позициями (переупорядочить), переменные считываются (загружаются) и записываются (хранятся). , операция имеет до и после, JMM делит стратегию вставки барьера памяти на 4 вида:
- Вставьте барьер StoreStore перед каждой энергозависимой записью
- Вставьте барьер StoreLoad после каждой энергозависимой записи
- Вставьте барьер LoadLoad после каждого чтения volatile
- Вставьте барьер LoadStore после каждого чтения volatile
1 и 2 описаны графически, и соответствующие правила таблицы следующие:
3 и 4 описаны графически, и соответствующие правила таблицы следующие:
На самом деле граф также является воплощением содержимого таблицы, но он просто говорит вам, как барьер памяти запрещает переупорядочивать инструкции, поэтому вам просто нужно помнить о содержимом таблицы.
Чтение и запись программы обычно не так просты, как в двух вышеприведенных случаях.Как можно использовать эти барьеры в комбинации? На самом деле это совсем не сложно, надо просто занести эти инструкции в таблицу в начале статьи, а потом склеить инструкции по порядку программы.
Давайте посмотрим на небольшую программу:
public class VolatileBarrierExample {
private int a;
private volatile int v1 = 1;
private volatile int v2 = 2;
void readAndWrite(){
int i = v1; //第一个volatile读
int j = v2; //第二个volatile读
a = i + j; //普通写
v1 = i + 1; //第一个volatile写
v2 = j * 2; //第二个volatile写
}
}
Принесение барьерной инструкции в программу выглядит так:
Давайте посмотрим на вышеуказанное изображение из нескольких угла:
- Цвет — это весь контент, сгенерированный за счет внесения в программу инструкции барьера, то есть «наиболее безопасное» решение, сгенерированное компилятором
- Очевидно, что многие барьеры избыточны. Барьер, на который указывает пунктирная рамка справа, — это барьер, который можно удалить с помощью **"оптимизации"**.
К этому моменту вы должны понять, как volatile гарантирует, что программа не будет «произвольно» сортироваться через барьеры памяти.
семантика энергозависимой памяти записи-чтения
Вспоминая программу из предыдущей статьи, предполагая, что поток A сначала выполняет метод записи, а затем поток B выполняет метод чтения:
public class ReorderExample {
private int x = 0;
private int y = 1;
private volatile boolean flag = false;
public void writer(){
x = 42; //1
y = 50; //2
flag = true; //3
}
public void reader(){
if (flag){ //4
System.out.println("x:" + x); //5
System.out.println("y:" + y); //6
}
}
}
Вы все еще помните JMM, о котором я говорил раньше?Да, вы все еще помните😂, когда поток A выполняет метод записи, посмотрите на картинку ниже:
Поток A записывает переменные, измененные в локальной памяти, обратно в основную память.
Семантика памяти для чтения volatile:
При чтении энергозависимой переменной JMM аннулирует соответствующую локальную память потока. Затем поток будет читать общую переменную из основной памяти.
Итак, когда поток B выполняет метод чтения, структура графа становится такой:
Переменная локальной памяти потока B недействительна, и переменная считывается из основной памяти в локальную память, и получается результат изменения потока A. Так volatile гарантирует видимость
Если вы видели предыдущую статью, вы даже не понимаете две картинки выше, объедините это:
- Thread A записывает летучую переменную, по сути, поток A отправляет сообщение (модификация общей переменной) в резьбу, которая будет прочитать летучную переменную
- Поток B читает изменчивую переменную, по сути, поток B получает сообщение, отправленное потоком ранее (модификация общей переменной перед записью volatile переменной).
- Поток A записывает изменчивую переменную, а затем поток B считывает изменчивую переменную.Этот процесс, по сути, представляет собой поток A, отправляющий сообщение потоку B через основную память.
На этом этапе, при собеседовании на volatile, вам должно быть о чем поговорить, а также иметь более глубокое понимание семантики volatile.
пасхальные яйца
В предыдущей статье упоминалось это предложение:
С точки зрения семантики памяти volatile
写-读
с замком释放-获取
имеют одинаковые эффекты памяти; энергозависимая запись и освобождение блокировки имеют одинаковую семантику памяти; энергозависимое чтение имеет ту же семантику памяти, что и получение блокировки
Запомните последние две картинки в тексте.Когда мы говорим о синхронизированном, вы быстро поймете смысл этого предложения.Если вам интересно, вы можете сначала понять семантику записи-чтения синхронизированного.
Далее мы поговорим о контенте, связанном с блокировкой, так что следите за обновлениями...
вопрос души
- Если после волатильной записи прямого возврата, он также генерирует команду «хранилище»?
- Как синхронизируется, насколько прогрессивно оптимизируется?
инструменты повышения производительности
tool.lu
tool.luЭто онлайн-инструмент, объединяющий множество функций, который в основном отвечает потребностям ежедневной разработки.
Рекомендуемое чтение
- На этот раз в мир параллелизма, пожалуйста, не пропустите
- Чтобы научиться параллельному программированию, необходимо глубокое понимание этих трех основных элементов.
- Есть три источника одновременных ошибок, пожалуйста, следите за ними.
- Наглядность и упорядоченность, Бывает-прежде чем это сделать
- Решить проблему атомарности?你首先需要的是宏观理解
Добро пожаловать, чтобы продолжать обращать внимание на общественный номер: «Сун Гун И Бин».
- Передовая технология Java для обмена галантереей
- Резюме эффективных инструментов | Ответ на «Инструменты»
- Анализ вопроса интервью и ответ
- Сбор технических данных | Ответ на «данные»
Узнайте о стеке технологий Java легко и весело, думая о чтении детективных романов, и постепенно разлагайте технические проблемы, основываясь на принципах упрощения сложных проблем, конкретизации абстрактных проблем и графики.Технология постоянно обновляется, пожалуйста, продолжайте платить внимание...