интервьюер:Сегодня я хочу поговорить с вами о модели памяти Java, вы слышали об этом?
Кандидат: Хорошо, позвольте мне кратко объяснить мое понимание. Итак, позвольте мне начать с того, почему существует модель памяти Java.
интервьюер: Давайте начнем ваше шоу.
Кандидат: Тогда позвольте мне сначала поговорить о предыстории.
Кандидат: 1. Существующие компы часто бывают многоядерными, и под каждое ядро есть кеш. Рождение кеша связано с «разницей в скорости процессора и памяти (основной памяти)», а кеши L1 и L2 вообще «исключительны для каждого ядра».
Кандидат: 2. Чтобы повысить эффективность работы ЦП, процессор может выполнять «неупорядоченное выполнение» входного кода, что является так называемым «переупорядочиванием инструкций».
Кандидат: 3. Операция модификации на значении часто не атомная (например, I ++ фактически разделена на несколько инструкций, когда компьютер выполнен)
Кандидат: Под вечным одиночным потоком нет проблем с вышеперечисленным, потому что одиночный поток означает отсутствие параллелизма. И в рамках одного потока компилятор/среда выполнения/процессор должны соответствовать семантике как-если-последовательно, что означает, что они не будут переупорядочивать «операции, зависящие от данных».
Кандидат: Для эффективности в процессоре есть кэши, переупорядочение инструкций и т. д., и вся архитектура усложнилась. Программы, которые мы пишем, также должны «полностью» использовать ресурсы процессора! Итак, мы использовали многопоточность
Кандидат: Многопоточность означает параллелизм, а параллелизм означает, что нам нужно учитывать вопросы безопасности потоков.
Кандидат: 1. Несоответственный кэш-данные: несколько потоков изменяют «общие переменные» одновременно, а кэш под сердечником CPU является «не совместно». Как синхронизировать данные между несколькими кешами и памятью?
Кандидат: 2. Переупорядочивание инструкций ЦП при многопоточности приведет к неожиданному выполнению кода, что в конечном итоге приведет к ошибкам в результатах.
Кандидат: Для проблемы "несоответствия кеша" у ЦП тоже есть свои решения, есть два общеизвестных:
Кандидат: 1. Используйте «блокировку шины». Пока ядро изменяет данные, другие ядра не могут изменять данные в памяти. (По аналогии с концепцией эксклюзивной памяти, пока модифицируется ЦП, другие ЦП должны ждать освобождения текущего ЦП)
Кандидат: 2 кэш когерентный протокол (протокол МЭСИ, на самом деле протоколов много, просто дайте всем посмотреть). MESI открыт на английском языке (Modified (модифицированное состояние), Exclusive (эксклюзивное состояние), Share (общее состояние), Invalid (неактивное))
Кандидат: Я думаю, что протокол когерентности кеша можно понимать как «замок кеша», который направлен на «запирание» «линии кеша». Так называемая «линия кеша» на самом деле является наименьшей единицей хранения кеша.
интервьюер:В порядке…
Кандидат: принцип протокола MESI, вероятно, таков: прежде чем каждый ЦП прочитает общую переменную, он сначала идентифицирует «состояние объекта» (модифицированный, общий, эксклюзивный или недопустимый) данных.
Кандидат: Если это монопольно, это означает, что переменные данные, которые должны быть получены текущим ЦП, являются самыми последними и не были прочитаны другими ЦП в то же время.
Кандидат: Если он является общим, это означает, что переменные данные, которые должны быть получены текущим ЦП, все еще являются самыми последними, и другие ЦП одновременно считывают их, но они не были изменены.
Кандидат: Если это модификация, это означает, что текущий ЦП изменяет значение переменной, и в то же время он отправляет уведомление о том, что статус данных недействителен для других ЦП. запишет кэшированные данные в основную память и изменит ее состояние с modify (модифицировать) на эксклюзивный (эксклюзивный)
Кандидат: Если он недействителен, это означает, что текущие данные были изменены, и последние данные необходимо перечитать из основной памяти.
Кандидат: На самом деле протокол MESI оценивает «статус объекта» и вырабатывает различные стратегии в соответствии с «статусом объекта». Суть в том, что когда определенный ЦП изменяет данные, ему необходимо «синхронизироваться», чтобы уведомить другие ЦП, указывая, что данные были изменены мной, и вы больше не можете их использовать.
Кандидат: По сравнению с "блокировкой шины" "зернистость блокировки" протокола МЭСИ меньше, а производительность однозначно будет выше.
интервьюер:Но насколько я понимаю, ЦП все же оптимизирован, вы еще не в курсе?
Кандидат: Ну я еще немного понимаю.
Кандидат: Из вышеизложенного видно, что когда ЦП изменяет данные, ему необходимо «синхронизироваться», чтобы сообщить другим ЦП, и ждать, пока другие ЦП ответят, чтобы получить недействительные (недействительные), прежде чем он сможет записать данные кэша в основную память.
Кандидат: Синхронный, что означает ожидание, а ожидание означает, что ничего нельзя сделать. ЦП точно не радует, поэтому опять оптимизируется.
Кандидат: Идея оптимизации состоит в том, чтобы перейти от «синхронного» к «асинхронному».
Кандидат: Когда изменения будут «синхронизировать», чтобы сказать другое ЦП, и теперь поставить новое модифицированное значение записывается в «Буфер хранения» и уведомляет, что другой CPU не забудьте изменить состояние, то ЦП возвращается напрямую для выполнения других вещей. Отправлено, пока другой CPU не получает ответное сообщение, то обновление данных в кэш.
Кандидат: когда другие процессоры получают недопустимое (недействительное) уведомление, они также помещают полученное сообщение в "недопустимую очередь". данные о том, что статус был установлен на «недействительный».
Кандидат: А асинхронность принесет новые проблемы: теперь я закончил модифицировать ценность CPU и записал его на «буфер магазина», и ЦП может делать другие вещи. Затем, если ЦП снова получает инструкцию и необходимо изменить значение, но последнее модифицированное значение все еще находится в «буфере хранилища» и не был изменен в кэш.
Кандидат: Таким образом, когда ЦП читает, ему нужно перейти к «буферу хранения», чтобы увидеть, существует ли хранилище. Если оно существует, оно будет выбрано напрямую. Если оно не существует, будут считаны данные в основной памяти. . 【Переадресация магазина】
Кандидат: Ну, проблема, вызванная первым асинхронным, была решена. (Одно и то же ядро считывает и записывает данные. Из-за асинхронности вполне вероятно, что второе чтение все еще будет старым значением, поэтому «буфер хранения» читается первым.
интервьюер:Есть другие?
Кандидат: Конечно, тогда "асинхронизация" вызовет проблемы с чтением и записью общих переменных одного ядра, и, конечно же, также вызовет проблемы с чтением и записью общих переменных "разных" ядер.
Кандидат: CPU1 изменяет значение и написал модифицированное значение для «буфера хранения» и уведомлять CPU2 для недействительной (недействительной) операции на этом значере, и CPU2 не может получать недействительные (неверные) уведомления и выполнять другие операции, приводящие к Еще старая ценность процессора 2.
Кандидат: Даже если ЦП2 получает недопустимое (недействительное) уведомление, но значение ЦП1 не было записано в основную память, когда ЦП2 снова считывает из основной памяти, это все еще старое значение...
Кандидат: часто существует "корреляция" между переменными (a=1;b=0;b=a), которая не зависит от процессора...
Кандидат: В общем, из-за асинхронной оптимизации "сохранения буфера" и "недействительной очереди", выполняемой ЦП по "протоколу когерентности кеша", очень вероятно, что результаты выполнения предыдущих инструкций могут быть не найдены в следующих инструкциях. (порядок выполнения каждой инструкции не является порядком выполнения кода), это явление часто называют «неправильным выполнением ЦП».
Кандидат: Для решения проблемы выхода из строя (которая также может быть понята как проблема видимости, модификация не синхронизируется с другими процессорами во времени) и введено понятие «барьер памяти».
интервьюер:В порядке…
Кандидат: «Барьер памяти» на самом деле предназначен для решения проблемы «асинхронной оптимизации», вызывающей «неупорядоченное выполнение ЦП» / «кэш не виден вовремя», так как это решить? Ну это "отключить" "асинхронную оптимизацию" (:
Кандидат: Барьеры памяти можно разделить на три типа: барьеры записи, барьеры чтения и всемогущие барьеры (включая барьеры чтения и записи).Барьер можно просто понять как: при работе с данными вставить в данные «специальную инструкцию». Пока встречается эта инструкция, предыдущие операции должны быть «завершены».
Кандидат: Написать барьер, который можно понять: CPU, когда вы замечаете инструкцию барьерного барьера, инструкция «раньше» существует в «Буфер магазина», все команды записи щеткой в кэше.
Кандидат: Таким образом, данные, измененные ЦП, могут быть немедленно представлены другим ЦП для достижения эффекта видимости «операции записи».
Кандидат: Барьер чтения аналогичен: когда ЦП находит инструкцию для чтения барьера, он обрабатывает все инструкции, существовавшие в «недопустимой очереди» «до».
Кандидат: Таким образом, вы можете убедиться, что текущее состояние кэша ЦП является точным, а «операция чтения» должна быть последним эффектом.
Кандидат: Так как система кэширования разных архитектур ЦП разная, протокол согласованности кэша разный, политика переупорядочивания разная, инструкции барьера памяти разные, чтобы упростить работу Java-разработчиков. Java инкапсулирует набор спецификаций, этот набор спецификаций называется «Модель памяти Java».
Кандидат: Более подробно, «Модель памяти Java» надеется скрыть различия в доступе различного оборудования и операционных систем, чтобы гарантировать, что Java-программы могут получать согласованные результаты при доступе к памяти на различных платформах. Цель состоит в том, чтобы решить проблемы атомарности, видимости (согласованности кеша) и упорядочения многопоточности.
интервьюер:Тогда почему бы нам просто не поговорить о спецификации и содержании модели памяти Java?
Кандидат: Нет, боюсь, в следующий раз будет вечерний разговор?
Резюме этой статьи:
-
Тремя основными причинами проблем параллелизма являются «видимость», «упорядоченность» и «атомарность».
-
Видимость: есть кэши под архитектурой ЦП, кэши L1/L2 под каждым ядром не разделены (не видны)
-
Упорядоченность: есть три основных области, которые могут привести к нарушению
- Оптимизация компилятора вызывает переупорядочивание (компилятор может выполнять однопоточные программы без изменения семантики, может быть скорректирован переупорядоченный порядок операторов кода)
- Параллельное переупорядочивание набора инструкций (ЦП может изначально переупорядочивать инструкции)
- Переупорядочивание системы памяти (архитектура ЦП, вероятно, имеет буфер хранения / недопустимый буфер очереди, эта «асинхронность», вероятно, вызовет переупорядочение инструкций)
-
Атомарность: оператор в Java часто требует выполнения нескольких инструкций ЦП (i++).Из-за переключения потоков операционной системы операция i++ может быть не завершена, и другие потоки обрабатывают общую переменную i «на полпути», что приводит к конечный результат не тот, что мы ожидали.
-
На уровне ЦП, чтобы решить проблему «когерентности кеша», необходимо обеспечить связанные «блокировки», такие как «блокировки шины» и «блокировки кеша».
- Блокировка шины — это блокировка шины, и изменения общих переменных позволяют одновременно выполнять только одну операцию ЦП.
- Блокировка кэша - это блокировка строки кэша (линии кэша), среди которых наиболее известен протокол МЭСИ.Состояние строки кэша маркируется, а видимость и упорядоченность (линии кэша) данных реализуется посредством "синхронизированного уведомления" .
- Но «синхронное уведомление» повлияет на производительность, поэтому будет буфер памяти (буфер хранения/недействительная очередь) для достижения «асинхронности» и повышения эффективности работы ЦП.
- После введения буфера памяти возникнут проблемы с «видимостью» и «беспорядком». В большинстве случаев в большинстве случаев можно пользоваться преимуществами «асинхронности», но в некоторых случаях требуется сильная «видимость» и «Порядок». и может только "отключить" оптимизацию кеша.
- «Отключенная» оптимизация кеша имеет «барьер памяти» на уровне ЦП, барьер чтения/записи/всесторонний барьер, по существу вставляя «инструкцию барьера», чтобы заставить буфер (сохранить буфер/недействительную очередь) работать перед инструкцией барьера Все были обработаны таким образом, что операции чтения и записи видны и упорядочены на уровне ЦП.
-
Различные реализации ЦП имеют различную архитектуру и оптимизацию.Чтобы скрыть различные различия в аппаратном обеспечении и доступе операционной системы к памяти, Java предлагает спецификацию «Модель памяти Java», которая гарантирует, что Java-программы могут получать доступ к памяти на различных платформах.
Добро пожаловать в мой публичный аккаунт WeChat【Java3y] Давайте поговорим о Java-интервью, серия онлайн-интервьюеров постоянно обновляется!
Серия [Онлайн-интервьюер-Мобильный терминал]Продолжаем обновлять два раза в неделю!
【Онлайн-интервьюер-компьютер】СерияПродолжаем обновлять два раза в неделю!
Оригинал это не просто! ! Проси три! !