anchor.diff:  
   === *Что такое Safe Publishing?*
   
  -_Safe Publishing_ - безопасная публикация. Это значит, что изменение состояние
  -объекта будет видно тому, кто в этом заинтересован.
  +_Safe Publishing_ - безопасная публикация. Это значит, что изменение состояние объекта будет видно тому, кто в этом заинтересован.
   
   === *Как сделать Safe Publishing используя volatile?*
   
  -Для корректной публикации достаточно объявить ссылку на объект как _volatile_.
  -В этом случае все чтения увидят полностью сконструированный последний записанный
  -объект.
  +Для корректной публикации достаточно объявить ссылку на объект как _volatile_. В этом случае все чтения увидят полностью сконструированный последний записанный объект.
   
   === *Как сделать Safe Publishing используя synchronized?*
   
  -Для того, чтобы безопасно опубликовать объект с помощью synchronized, нужно
  -изолировать все действия с ним в synchronized блоке.
  -
  -Поток, входящий в критическую секцию, всегда увидит последнее корректное
  -состояние объекта.
  +Для того, чтобы безопасно опубликовать объект с помощью synchronized, нужно изолировать все действия с ним в synchronized блоке. Поток, входящий в критическую секцию, всегда увидит последнее корректное состояние объекта.
   
   === *Как сделать Safe Publishing используя AtomicBoolean?*
   
  -У `AtomicBoolean` точно же такая семантика как и у _volatile_. Для того, чтобы
  -безопасно опубликовать объект через `AtomicBoolean`, достаточно перед чтением
  -объекта сначала прочитать `AtomicBoolean` переменную, а после изменения
  -записать ее.
  +У `AtomicBoolean` точно же такая семантика как и у _volatile_. Для того, чтобы безопасно опубликовать объект через `AtomicBoolean`, достаточно перед чтением объекта сначала прочитать `AtomicBoolean` переменную, а после изменения записать ее.
   
   === *Что такое Монитор?*
   
  -Монитор - объект синхронизации, которым обладает каждый Java-объект. Для того,
  -чтобы войти в критическую секцию, потоку сначала нужно захватить монитор.
  -Если монитор уже захвачен другим потоком, то этот поток переходит в состояние
  -**BLOCKING**. После того как поток выходит из критической секции, он отпускает
  -монитор. 
  -
  -Также мониторы имеют встроенный механизм ожидания и пробуждения на
  -определенных условиях. При переходе в режим ожидания поток попадает в wait-set
  -монитора и другой поток может пробудить его после наступления условия. 
  -
  -Наличие монитора у каждого объекта позволяет не использовать внешние мьютексы,
  -а организовывать критическую секцию с помощью конструкции языка synchronized,
  -которая по умолчанию использует монитор текущего объекта.
  +Монитор - объект синхронизации, которым обладает каждый Java-объект. Для того, чтобы войти в критическую секцию, потоку сначала нужно захватить монитор. Если монитор уже захвачен другим потоком, то этот поток переходит в состояние **BLOCKING**. После того как поток выходит из критической секции, он отпускает монитор. Также мониторы имеют встроенный механизм ожидания и пробуждения на определенных условиях. При переходе в режим ожидания поток попадает в wait-set монитора и другой поток может пробудить его после наступления условия. Наличие монитора у каждого объекта позволяет не использовать внешние мьютексы, а организовывать критическую секцию с помощью конструкции языка synchronized, которая по умолчанию использует монитор текущего объекта.
   
   === *Расскажите о взаимодействии synchronized/Object.wait()/.notify()/.notifyAll()*
   
  -Каждый монитор имеет механизм ожидания и пробуждения. После того как поток
  -захватил монитор, он может обнаружить, что условие для продолжения работы еще
  -не наступило (скажем, данные еще не готовы). В этом случае хочется не постоянно
  -проверять условие (при этом отпуская и захватывая монитор, чтобы дать другому
  -потоку шанс изменить состояние условия), а уснуть, отдать монитор и получить
  -нотификацию, когда условие будет выполнено.
  -
  -Эта функциональность достигается с помощью методов `wait`, `notify` и
  -`notifyAll`. После того как поток захватил монитор и вошел в критическую секцию,
  -организованную с помощью `synchronized`, он может вызывать метод `wait`. В этом
  -случае он перейдет в wait-set монитора и отпустит монитор. При этом поток
  -заблокируется и перейдет в состояние **WAITING**. Другой поток может захватить
  -монитор и войти в критическую секцию, выполнить определенные действия и вызвать
  -метод `notify` или `notifyAll`. После того как один из этих методов вызван,
  -поток ждущий на событие, удаляется из wait-set монитора и переходит в состояние
  -**BLOCKING** и пытается захватить монитор. После того, как поток, который
  -вызвал `notify` освобождает монитор, блокирующий поток захватывает монитор и
  -переходит в состояние **RUNNABLE**.
  -
  -`notify` от `notifyAll` отличается тем, что первый пробуждает один из потоков в
  -списке ожидания, в тоже время как последний пробуждает все потоки. Почти всегда
  -более разумно всегда вызывать `notifyAll`, т.к. вызов этого метода дает шанс
  -всем потокам получить монитор и он работает правильно в независимости от
  -количества потоков в списке ожидания.
  +Каждый монитор имеет механизм ожидания и пробуждения. После того как поток захватил монитор, он может обнаружить, что условие для продолжения работы еще не наступило (скажем, данные еще не готовы). В этом случае хочется не постоянно проверять условие (при этом отпуская и захватывая монитор, чтобы дать другому потоку шанс изменить состояние условия), а уснуть, отдать монитор и получить нотификацию, когда условие будет выполнено. Эта функциональность достигается с помощью методов `wait`, `notify` и `notifyAll`. После того как поток захватил монитор и вошел в критическую секцию, организованную с помощью `synchronized`, он может вызывать метод `wait`. В этом случае он перейдет в wait-set монитора и отпустит монитор. При этом поток заблокируется и перейдет в состояние **WAITING**. Другой поток может захватить монитор и войти в критическую секцию, выполнить определенные действия и вызвать метод `notify` или `notifyAll`. После того как один из этих методов вызван, поток ждущий на событие, удаляется из wait-set монитора и переходит в состояние **BLOCKING** и пытается захватить монитор. После того, как поток, который вызвал `notify` освобождает монитор, блокирующий поток захватывает монитор и переходит в состояние **RUNNABLE**.
  +
  +`notify` от `notifyAll` отличается тем, что первый пробуждает один из потоков в списке ожидания, в тоже время как последний пробуждает все потоки. Почти всегда более разумно всегда вызывать `notifyAll`, т.к. вызов этого метода дает шанс всем потокам получить монитор и он работает правильно в независимости от количества потоков в списке ожидания.
   
   === *Реализуйте ограниченную блокирующую очередь на synchronized/Object.wait()/.notify()/.notifyAll()*
   
  
positive.code: * MIMD - вычислительные системы с несколькими потоками данных и несколькими
  потоками инструкций (распределенные системы).
  
  Одноядерные процессоры относятся к SISD системам, многоядерные процессоры
  к SIMD или MIMD. GPU является SIMD системой, потому что использует векторные
  инструкции для операций над мультимедиа-данными.
  
  === *Расскажите про иерархию кэшей L1/L2/L3? Что вызвало ее появление*
  
  
negative.code: 
  === *Что такое частичный порядок?*
  
  Частичный порядок - это математическое концепция, которая описывает отношение, которое обладает свойствами рефлексивности, антисимметричности и транзитивности. 
  
  * Рефлексивность означает, что отношение, примененное к одинаковым аргументам, является истинным.
  * Антисимметричность означает, что отношение не симметрично. То есть отношение, примененное к неодинаковым аргументам, поменняными местами, будет ложным.
  * Транзитивность означает, что если отношение истинно для аргументов *A* и *B* и для аргументов *A* и *C*, то оно истинно для аргументов *A* и *C*.
  
  Примером отношения частичного порядка является отношение *"быть делителем"*.
  
  === *Что такое отношение happens-before?*
  
  Отношение *happens-before*(происходит-до) является отношением частичного порядка между двумя операциями. Если одна операция *происходит до* другой, то ее результат видим и упорядочен для другой.
  
  === *Почему happens-before — это частичный порядок?*
  
  Потому что оно удовлетворяет определению частичного порядка.
  
  * Рефлексивность. Результат самой операции, очевидно, видим и упорядочен для  нее самой.
  
  * Антисимметричность. Если результат операции *A* видим и упорядочен для операции *B*, то результат операции *B* бы не видим и не упорядочен для *A*.
  
  Если бы *B* была бы видна для *A*, это значит, что для ее (*A*) локального времени *B* произошла до *A*. Так как результат *A* виден для *B*, то это значит, что для ее (*B*) локального времени *A* произошла до *B*. Так как отношение "произошел до/был раньше" транзитивно, из этого следует что *B* произшла до *B*. Получаем противоречие. Следовательно, *B* не может быть видна для *A*.
  
  * Транзитивность. Если результат операции *A* видим и упорядочен для *B* и результат *B* видим и упорядочен для *C*, то результат *A* видим и упорядочен для *С*.
  
  Так как *A* видна для *B*, то она произошла до *B* в ее локальном времени. Так как *B* видима для *C*, то она произошла до *C* в ее локальном времени. Так как отношение "произошел до/был раньше" транзитивно, то и операция *A* видима для *C*.
  
  === *Что такое data-race?*
  
  Data-race — это ситуация, когда несколько потоков одновременно/конкуретно работают с одной ячейкой памяти, и хотя бы один из них в нее пишет. В этом случае происходит "гонка". Результат чтения недетерминирован, так как зависит от того, какой из потоков выиграет "гонку" на физическом уровне.
  
  === *Какие гарантии на работу с volatile?*
  
  Запись в volatile поле *happens-before* чтения из volatile поля. 
  
  Соответственно, поток читающий из volatile поля гарантировано увидит корректное значение записи в это поля (а также всех предыдущих записей в потоке,изменившем это поле). Компилятору также запрещену переупорядочивать инструкции, которые работают с volatile полями с другими инструкциями. 
  
  То есть JMM *гарантирует*, что записи в потоке A, которые произошли до записи в volatile-поле, произошли и видимы для потока B, который читает это поле. 
  
  === *Какие гарантии на работу с final?*
  
  Запись в *final* поле (примитив, массив или иммутабельный объект) в конструкторе объекта сразу видима после завершение конструктора. Это позволяет быть уверенным, что иммутабельный объект корректно публикуется между потоками, даже в присутствии гонки, без дополнительной синхронизации.
  
  === *Вычисление hashCode у java.lang.String имеет data race — Вас это не пугает?*
  
  Нет, потому что поле *hash* в классе *String* имеет тип *int*. JMM гарантирует, что запись в 32-битную переменную всегда будет атомарна. Поэтому мы  можем в нем увидеть либо 0, либо корректно вычисленное значение хэш-кода. У нас нет необходимости сразу увидеть вычисленный хэш-код. Это поле является всего лишь оптимизацией кэширования вычисления. Если поток увидет в нем 0, то просто еще раз сделает вычисление. Это решение видится вполне логичным инженерным компромиссом.
  
  === *Объясните смысл выражения «data race free программа является sequential consistent».*
  
  Программа является *sequential consistent*, если ее действия на всех процессорах выполняются в каком-то последовательном порядке, и операции на каждом процессоре выполняются в программном порядке.  *Data race free* означает, что в программе нет одновременных чтений-записей в одну ячейку памяти. Так как у нас нет конфликтов между чтениями и записями, то мы можем построить последовательный порядок, в котором выполняются операции. Внутри же процесса операции могут быть перестановлены как угодно. При этом программный порядок не нарушится, а перестановки не будут иметь эффект на другие процессоры.
  
  === *Что такое ordering, visibility, atomicity, happend-before, mutual exclusion на примере volatile?*
  
  *Ordering* - компилятору запрещено переставлять инструкции, которые работают с volatile переменными. То есть мы можем быть уверенными, что инструкции до volatile выполнились, а после него еще не начались. 
  
  *Visibility* - записи в volatile переменные видимы для всех последующих чтений.
  
  *Atomicity* - записи в volatile переменные атомарны в независимости от разрядности. Т.е записи volatile long и double поля всегда будут атомарны, в отличие от "голых" long и double.
  
  *Happens-before* - с практической точни зрения это комбинация видимости и упорядочивания. Все записи в volatile поля имеют отношение *happens-before* по отношению к чтениям.
  
  *Mutual exclusion* - volatile не гарантирует взаимного исключения. То есть операции с volatile полями не блокируют друг друга. volatile гарантирует, что чтение переменной увидит последнюю запись в нее, но не засчет взаимного исключения. 
  
  === *Что такое ordering, visibility, atomicity, happend-before, mutual exclusion на примере synchronized?*
  
  *Ordering* - компилятору запрещено переставлять инструкции в критической секции, выделенной с помощью *synchronized* с остальными инструкциями. То есть все операции выполняются до входа в критическую секцию и ни одна не начинается после ее окончания.
  
  *Visibility* - записи в переменные внутри критической секции видимы для последующих чтений внутри этой же критической секции.
  
  *Atomicity* - *synchronized* организуюет критической секцию. Все действия в критической секции выполняются только одним процессом, поэтому они являются атомарными. Конечно, при условии, что доступ к данным осуществляется только в критической секции.
  
  *Happens-before* - вход в *synchronized* блок создает отношение *happens-before* выходу из него.
  
  *Mutual exclusion* - *synchronized* создает критическую секцию и гарантирует взаимное исключение.
  
  === *Что такое ordering, visibility, atomicity, happend-before, mutual exclusion на примере AtomicInteger?*
  
  У *AtomicInteger* такие же гарантии на *ordering*, *visibility* и *happens-before*, как и у *volatile*, потому что поле *value* внутри него объявлено как *volatile*.
  
  *Atomicity* - чтение и запись в `AtomicInteger` атомарны. Атомарность достигается засчет механизма CAS. CAS-инструкции позволяют атомарно обновить ячейку памяти или получить ошибку в случае, если состояние ячейки изменилось во время операции. В случае конфликта выполняется повтор операции до ее успешного выполнения.
  
  *Mutual exclusion* - `AtomicInteger` не гарантирует взаимного исключения. Несколько процессов могут одновременно читать его значение, но писать может только один.
  
  === *Атомарно ли ++ для volatile переменной?*
  
  Нет, так как в реальности ++ представляет из себя 3 инструкции: чтение, инкремент и запись. *volatile* гарантирует только атомарность одиночной записи (мы не увидим шум внутри поля), но не атомарность набора операций. То есть никто не запрещает 2 процессам прочитать одинаковое значение переменной, сделать инкремент и записать его в память. В этом случае мы получим "потерянную запись". 
  
  ==  Базовое API, примитивы/конструкции
  
  === *Thread.getState() возвращает экземпляр Thread.State. Какие возможны значения?*
  
  * *NEW* - поток был создан, но еще не стартовал; 
  * *RUNNABLE* - поток выполняется. Этот статус не обязательно значит, что поток выполняет код. Это всего лишь значит, что поток доступен планировщику потоков для выбора потока на исполнение;
  * *WAITING* - поток ждет на мониторе; Поток переходит в него вызовами методов  `wait()`, `join()` либо парковкой через `LockSupport.park()`
  * *TIME_WAITING* - поток ждет на мониторе с таймаутом; Те же самые методы, только  с таймаутом + `sleep`.
  * *BLOCKED* - поток заблокирован на мониторе; Поток переходит в него когда пытается войти в критическую секцию, но она уже занята другим потоком. 
  * *TERMINATED* - поток завершил выполнение. 
  
  === *Отличие Thread.start() и Thread.run()?*
  
  `Thread.start()` в отличие от `Thread.run()` переводит поток в состояние RUNNABLE и запускает код независимо от текущего потока. В случае же вызова `Thread.run()` код выполнит тот же поток, который вызвал этот метод. Семантически эти 2 метода совершенно различны: `run` отвечает за задачу, которую нужно выполнить независимо, а `start` за поднятие инфрастуктуры по выполнению этой задачи.
  
  === *Что происходит при вызове Thread.interrupt()?*
  
  Потоку, для которого вызвали этот метод, выставляется флаг того, что он прерван. Код, исполняющийся в этом потоке, может периодически проверять этот флаг на предмет того, что ему нужно завершить выполнение. Если поток в момент вызова `interrupt` спал, ждал, был заблокирован на мониторе или на I/O(InterruptibleChannel), то выбросится `InterruptedException` и флаг прерывания сбросится. Программист имеет возможность обработать `InterruptedException`, выполнить действия по безопасному завершению и решить, что делать дальше (пробросить исключение, восстановить статус прерывания или завершить работу).
  
  === *Что происходит при вызове Thread.stop()?*
  
  При вызове `Thread.stop` поток отпускает все мониторы, которые он держал,  выкидавает ошибку `ThreadDeath` и завершается принудительно.
  
  === *Почему Thread.stop()/destroy()/suspend()/resume() — deprecated?*
  
  Потому что они небезопасны. Поток может быть прерван в любой момент и обязан отпустить все блокировки. То есть например во время атомарного обновления структуры данных, поток может прерваться и структура окажется в поврежденном состоянии. Это неприемлимо. Для того, чтобы защититься в коде нужно ловить `ThreadDeath`, обрабатывать его и пробрасывать дальше. Но такой подход не практичен, сильно усложняет код и поддерживает плохую практику убивания ресурсов без их очистки.
  
  === *Перечислите все причины по которым может выскочить InterruptedException*
  
  