О чем следует говорить при опросе одновременных изменчивых ключевых слов?

Java
О чем следует говорить при опросе одновременных изменчивых ключевых слов?

Чтобы узнать больше интересного контента заранее, пожалуйста, посетителичный блог Чтобы узнать больше интересного контента заранее, пожалуйста, посетителичный блог Чтобы узнать больше интересного контента заранее, пожалуйста, посетителичный блог

написать впереди

существуетНаглядность и упорядоченность, Бывает-прежде чем это сделатьВ статье один из принципов случая-раньше: правило volatile-переменной

Запись в энергозависимый домен происходит до чтения энергозависимого домена в любом последующем

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

правила «происходит до» для volatile-переменных

Вы помните форму ниже? (да, ты помнишь 😂)

Можно ли переупорядочить вторая операция вторая операция вторая операция
первое действие Обычное чтение/запись изменчивое чтение изменчивая запись
Обычное чтение/запись - - NO
изменчивое чтение NO NO NO
изменчивая запись - NO NO

上面的表格是 JMM 针对编译器定制的 volatile 重排序的规则,那 JMM 是怎样禁止重排序的呢? ответбарьер памяти

Барьеры памяти / Заборы

Неважно, слышали вы этот термин или нет, он прост, и вы увидите

Чтобы достичь семантики памяти volatile, компилятор вставляет барьеры памяти в последовательность инструкций, чтобы запретить определенные типы переупорядочения процессора при генерации байт-кода.

Это предложение немного абстрактно, попробуйте представить, что барьер памяти — это высокая стена, если между двумя переменными есть этот барьер, то они не могут поменяться позициями (переупорядочить), переменные считываются (загружаются) и записываются (хранятся). , операция имеет до и после, JMM делит стратегию вставки барьера памяти на 4 вида:

  1. Вставьте барьер StoreStore перед каждой энергозависимой записью
  2. Вставьте барьер StoreLoad после каждой энергозависимой записи
  3. Вставьте барьер LoadLoad после каждого чтения volatile
  4. Вставьте барьер 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写
	}
}

Принесение барьерной инструкции в программу выглядит так:

Давайте посмотрим на вышеуказанное изображение из нескольких угла:

  1. Цвет — это весь контент, сгенерированный за счет внесения в программу инструкции барьера, то есть «наиболее безопасное» решение, сгенерированное компилятором
  2. Очевидно, что многие барьеры избыточны. Барьер, на который указывает пунктирная рамка справа, — это барьер, который можно удалить с помощью **"оптимизации"**.

К этому моменту вы должны понять, как 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 гарантирует видимость

Если вы видели предыдущую статью, вы даже не понимаете две картинки выше, объедините это:

  1. Thread A записывает летучую переменную, по сути, поток A отправляет сообщение (модификация общей переменной) в резьбу, которая будет прочитать летучную переменную
  2. Поток B читает изменчивую переменную, по сути, поток B получает сообщение, отправленное потоком ранее (модификация общей переменной перед записью volatile переменной).
  3. Поток A записывает изменчивую переменную, а затем поток B считывает изменчивую переменную.Этот процесс, по сути, представляет собой поток A, отправляющий сообщение потоку B через основную память.

На этом этапе, при собеседовании на volatile, вам должно быть о чем поговорить, а также иметь более глубокое понимание семантики volatile.

пасхальные яйца

В предыдущей статье упоминалось это предложение:

С точки зрения семантики памяти volatile写-读с замком释放-获取имеют одинаковые эффекты памяти; энергозависимая запись и освобождение блокировки имеют одинаковую семантику памяти; энергозависимое чтение имеет ту же семантику памяти, что и получение блокировки

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

Далее мы поговорим о контенте, связанном с блокировкой, так что следите за обновлениями...

вопрос души

  1. Если после волатильной записи прямого возврата, он также генерирует команду «хранилище»?
  2. Как синхронизируется, насколько прогрессивно оптимизируется?

инструменты повышения производительности

tool.lu

tool.luЭто онлайн-инструмент, объединяющий множество функций, который в основном отвечает потребностям ежедневной разработки.


Рекомендуемое чтение


Добро пожаловать, чтобы продолжать обращать внимание на общественный номер: «Сун Гун И Бин».

  • Передовая технология Java для обмена галантереей
  • Резюме эффективных инструментов | Ответ на «Инструменты»
  • Анализ вопроса интервью и ответ
  • Сбор технических данных | Ответ на «данные»

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