anchor.diff:  }
   ----
   
  -=== *Что такое Safe Publishing?*
  +=== Что такое Safe Publishing?
   
   _Safe Publishing_ - безопасная публикация. Это значит, что изменение состояние объекта будет видно тому, кто в этом заинтересован.
   
  -=== *Как сделать Safe Publishing используя volatile?*
  +=== Как сделать Safe Publishing используя volatile?
   
   Для корректной публикации достаточно объявить ссылку на объект как volatile. В этом случае все чтения увидят полностью сконструированный последний записанный объект.
   
  -=== *Как сделать Safe Publishing используя synchronized?*
  +=== Как сделать Safe Publishing используя synchronized?
   
   Для того, чтобы безопасно опубликовать объект с помощью synchronized, нужно изолировать все действия с ним в synchronized блоке. Поток, входящий в критическую секцию, всегда увидит последнее корректное состояние объекта.
   
  -=== *Как сделать Safe Publishing используя AtomicBoolean?*
  +=== Как сделать Safe Publishing используя AtomicBoolean?
   
   У `AtomicBoolean` точно же такая семантика как и у volatile. Для того, чтобы безопасно опубликовать объект через `AtomicBoolean`, достаточно перед чтением объекта сначала прочитать `AtomicBoolean` переменную, а после изменения записать ее.
   
  -=== *Что такое Монитор?*
  +=== Что такое Монитор?
   
   Монитор - объект синхронизации, которым обладает каждый Java-объект. Для того, чтобы войти в критическую секцию, потоку сначала нужно захватить монитор. Если монитор уже захвачен другим потоком, то этот поток переходит в состояние _BLOCKING_. После того как поток выходит из критической секции, он отпускает монитор. Также мониторы имеют встроенный механизм ожидания и пробуждения на определенных условиях. При переходе в режим ожидания поток попадает в wait-set монитора и другой поток может пробудить его после наступления условия. Наличие монитора у каждого объекта позволяет не использовать внешние мьютексы, а организовывать критическую секцию с помощью конструкции языка synchronized, которая по умолчанию использует монитор текущего объекта.
   
  -=== *Расскажите о взаимодействии synchronized/Object.wait()/.notify()/.notifyAll()*
  +=== Расскажите о взаимодействии synchronized/Object.wait()/.notify()/.notifyAll()
   
   Каждый монитор имеет механизм ожидания и пробуждения. После того как поток захватил монитор, он может обнаружить, что условие для продолжения работы еще не наступило (скажем, данные еще не готовы). В этом случае хочется не постоянно проверять условие (при этом отпуская и захватывая монитор, чтобы дать другому потоку шанс изменить состояние условия), а уснуть, отдать монитор и получить нотификацию, когда условие будет выполнено. Эта функциональность достигается с помощью методов `wait`, `notify` и `notifyAll`. После того как поток захватил монитор и вошел в критическую секцию, организованную с помощью `synchronized`, он может вызывать метод `wait`. В этом случае он перейдет в wait-set монитора и отпустит монитор. При этом поток заблокируется и перейдет в состояние _WAITING_. Другой поток может захватить монитор и войти в критическую секцию, выполнить определенные действия и вызвать метод `notify` или `notifyAll`. После того как один из этих методов вызван, поток ждущий на событие, удаляется из wait-set монитора и переходит в состояние _BLOCKING_ и пытается захватить монитор. После того, как поток, который вызвал `notify` освобождает монитор, блокирующий поток захватывает монитор и переходит в состояние _RUNNABLE_.
   
   `notify` от `notifyAll` отличается тем, что первый пробуждает один из потоков в списке ожидания, в тоже время как последний пробуждает все потоки. Почти всегда более разумно всегда вызывать `notifyAll`, т.к. вызов этого метода дает шанс всем потокам получить монитор и он работает правильно в независимости от количества потоков в списке ожидания.
   
  -=== *Реализуйте ограниченную блокирующую очередь на synchronized/Object.wait()/.notify()/.notifyAll()*
  +=== Реализуйте ограниченную блокирующую очередь на synchronized/Object.wait()/.notify()/.notifyAll()
   
   См. https://github.com/arteam/100-Java-Concurrency-questions/blob/master/bounded-blockinq-queue/src/main/java/com/github/arteam/bbqueue/BoundedBlockingQueue.java[bounded-blockinq-queue]
   
  -=== *Перечислите все сценарии попадания в blocking-set встроенного монитора*
  +=== Перечислите все сценарии попадания в blocking-set встроенного монитора*
   
   * Поток пытается захватить монитор, но другой монитор уже его держит
   * Поток спит на мониторе и пробуждается вызовом `notify()` или `notifyAll()`, но пока он просыпался, другой поток захватил монитор.
   
  -=== *Перечислите все сценарии выхода из blocking-set встроенного монитора*
  +=== Перечислите все сценарии выхода из blocking-set встроенного монитора
   
   * Поток, который держал монитор, отпустил его, выйдя из критической секции
   * В коде критической секции произошло исключение и поток был вынужден отпустить монитор
   
  -=== *Перечислите все сценарии попадания в wait-set встроенного монитора*
  +=== Перечислите все сценарии попадания в wait-set встроенного монитора
   
   * Поток, который держал монитор, вызвал метод `wait` на объекте.
   
  -=== *Перечислите все сценарии выхода из wait-set встроенного монитора*
  +=== Перечислите все сценарии выхода из wait-set встроенного монитора
   
   * Другой поток, держа монитор, вызвал метод `notify` или `notifyAll` на объекте
   * Если поток попал в список ожидания вызывом `wait` c таймаутом, то по истечении таймаута поток проснется
   * Поток, попавший в список ожидания, прерван вызывом `Thread.interrupt`
   * Поток может проснуться без видимой на то причины. ОС не запрещено это делать. Это называется _spurious wakeup_.
   
  -=== *Различия между Thread.isInterrupted() и Thread.interrupted()?*
  +=== Различия между Thread.isInterrupted() и Thread.interrupted()?
   
   `Thread.isInterruped()` является обычным методом, возвращает значение флага прерывания и не изменяет его. В то время как `Thread.interrupted()` является статическим методом, возвращает значение и устанавливает флаг в `false`.Трудно представить случай, когда следует использовать второй метод.
   
  -=== *Расскажите о идиоме многопоточного проектирования Private mutex*
  +=== Расскажите о идиоме многопоточного проектирования Private mutex
   
   Идея в том, объект содержит в себе в примитив синхронизации - бинарный семафор или мьютекс. С помощью мьютекса можно создавать критические секции. Каждый поток обязан захватить мьютекс при входе и отпустить его при выходе. Так как мьютекс приватный, то мы можем гарантировать, что его будут использовать только потоки, которые работают с объектом.
   
  -=== *Расскажите о идиоме многопоточного проектирования Spin lock/Busy waiting*
  +=== Расскажите о идиоме многопоточного проектирования Spin lock/Busy waiting
   
   Подход состоит в том, что в ситуации когда поток обнаруживает, что определенное условие еще не наступило и он не может продолжать свою работу, он вместо того, чтобы переходить в режим ожидания, пытается крутиться в цикле, проверяя условие. Идея в том, что если условие очень быстро меняется, то более разумно немного подождать в user-mode и жечь циклы процессора, чем переходить в тяжелый режим ожидания. Если на мониторе большая конкуренция, то мы не будем тратить время на накладные расходы по подъему и опусканию потоков, а выполнять операции быстрее, тратя в обмен на это процессорные ресурсы.
   
  -=== *Расскажите о идиоме многопоточного проектирования backoff protocol (expotential backoff)*
  +=== Расскажите о идиоме многопоточного проектирования backoff protocol (expotential backoff)
   
   Подход основывается на наблюдении о том, что когда несколько потоков одновременно запрашивают разделяемый ресурс и повторяют попытки в случае неудачи, то большинство запросов являются "холостыми", т.к. у ресурса слишком большая очередь потенциальных потребителей. Когда все потоки одновременно пытаются захватить ресурс - выигрывает только один. Остальным приходится опять повторять запросы. В итоге много процессорного времени тратится на бесполезную работу. Одним из решением этой проблемы является backoff. Каждый поток после неудачи засыпает на случайный промежуток времени. Если распределение времени сна хорошее, то когда поток проснется - велика вероятность, что ресурс будет свободен. Таким образом мы "рассасываем" очереди на ресурсе, назначая каждому потоку свое время прихода. Потоки, чья очередь еще не пришла, вместо того, чтобы жечь процессорные циклы - спят.
   
   _Expotential backoff_ - это протокол отката, по которому величина промежутка времени ожидания, из которого оно случайно выбирается, увеличивается в зависимости от количества неудачных попыток. Идея заключается в том, чтобы использовать количество отказов как эвристику для поиска оптимального времени ожидания. Чем больше неудач, тем шире нужно брать окно, чтобы уменьшить вероятность коллизий.
   
  -=== *Что это за свойство — «reentrancy»?*
  +=== Что это за свойство — «reentrancy»?
   
   *Reentrancy (повторное вхождение)* - это свойство блокировки, которое характеризуется тем, что поток, который держит лок, может захватить его сколько угодно раз. То есть это значит, что поток не может заблокироваться на самом себе. Это очень удобное свойство в ситуации, когда лок защищает несколько методов и эти методы взаимодействуют между собой.
   
  -=== *Что такое «poison message»?*
  +=== Что такое «poison message»?
   
   *Poison messsage* - это сообщение, которое не может быть обработано из-за ошибок (скажем, откатившейся транзакции), но продолжает сидеть в очереди и блокировать другие сообщения. Если очередь забьется такими сообщениями, то она перестанет обрабатывать нормальные сообщения и, фактически, прекратит обслуживание. Для предотвращения таких ситуаций в очереди должет быть параметр, который контролирует максимальное количество попыток доставки сообщения.
   
  -=== *Что такое «mutual exclusion»? Примеры как добиться в Java*
  +=== Что такое «mutual exclusion»? Примеры как добиться в Java
   
   *Mutual exclusion* - это требования выполнения участка кода только одним процессом/потоком в единицу времени. В этом случае участок кода называется критической секцией. В Java можно добиться с помощью synchronized блока, `ReentrantLock`, семафора с единичной длиной, блокирующей очередью в 1 элемент, spinloop на volatile флаге. Возможно, еще CAS (но в этом случае мы говорим не об участке кода, а об ячейке памяти).
   
  -=== *Что такое «condition waiting»? Примеры как добиться в Java*
  +=== Что такое «condition waiting»? Примеры как добиться в Java
   
   Честно говоря, не знаю такого термина. Подозреваю, имеется ввиду ситуация,когда поток обнаруживает ситуацию, в которой он не может продолжить выполнение (скажем, очередь заполнена), он вместо того, чтобы выбросить ошибку, подписывается на нотификацию, отдает лок и ждет пока наступит условие для продолжения (появилось свободное место в очереди). В Java можно добиться с помощью механизма `wait`/`notify` или класса `Condition` и помощью методов `await`/`signal`.
   
   ==  java.util.concurrent: Пулы потоков, Future
   
  -=== *Различия в интерфейсах Runnable и Callable*
  +=== Различия в интерфейсах Runnable и Callable
   
   Разница заключается в том, что `Callable` дает возможность выполнить определенный код и вернуть значение, а `Runnable` только выполнить код. Также код в `Callable` может выбросить проверямое исключение, в то время как в `Runnable` этого делать не позволяет. Исключение нужно оборачивать в непроверямое.
   
  -=== *Преимущества ScheduledThreadPool перед java.util.Timer*
  +=== Преимущества ScheduledThreadPool перед java.util.Timer
   
   * Можно задать несколько потоков для выполнения задач
   * Не умирает при возникновение исключения
  
positive.code: 
  Одноядерные процессоры относятся к SISD системам, многоядерные процессоры к SIMD или MIMD. GPU является SIMD системой, потому что использует векторные инструкции для операций над мультимедиа-данными.
  
  === *Расскажите про иерархию кэшей L1/L2/L3? Что вызвало ее появление*
  
  L1/L2/L3 - кэши данных, которыми оперирует процессор.
  
  
negative.code: * Рекомендуется для использования разработчиками Java, в то время как
  `Timer` считается устаревшим и используется только до Java 5.
  
  === Говорят, что Future/CompletableFuture — это монада. Что скажете?
  
  Если упростить до невозможности, то монада - это структура, позволяющая представить значение в контексте выполнения операции. То есть вместо того, чтобы работать с реальным значением, мы можем представить его контейнером и дальше оперировать контейнером как заместителем реального значения. У контейнера есть операции создания и преобразования в контейнер с другим содержимым. Это позволяет программисту  в некоторых местах сильно упростить код, когда его не интересуют промежуточное состояние. Он может работать с монадой как с реальным значением, не имея его представления. `Future` не является классической монадой, так как не позволяет преобразовывать себя в другие обещания выполнения. Можно только параметризировать `Future` типом и создать его (например, через `FutureTask`). В свою очередь `CompletableFuture` позволяет преобразовывать одни обещания выполнения в другие.
  
  === В чем преимущество ForkJoinPool над ThreadPoolExecutor?
  
  `ForkJoinPool` хорошо работает в случаях, когда задачи могут разделяться на подзадачи. Он использует work-stealing алгоритм, который позволяем потокам "красть" задачи, созданные в других потоках. `ThreadPoolExecutor` этого делать не может. Если задаче нужно себя разбить, то все её подзадачи будут выполняться в том же потоке последовательно, что может привести к нежелаемой ситуации, когда некоторые потоки работают активно, а другие простаивают без работы. 
  
  === Какая функциональность появилась у ScheduledThreadPool в сравнении с ThreadPoolExecutor?
  
  `ScheduledThreadPoolExecutor` позволяет запускать задачи по интервалу или с задержкой. С помощью методов `scheduleAtFixedRate` или `scheduleWithFixedDelay` можно запускать перодические задачи. `ThreadPoolExecutor` запускает задачи сразу как они доступны в очереди.
  
  === В чем отличие методов sheduleAtFixedRate() от sheduleAtFixedDelay() класса SheduledThreadPool?
  
  `sheduleAtFixedRate` не учитывает длину выполнения задачи и просто запускает задачи по интервалу. В то же время `sheduleAtFixedDelay` считает интервал ожидания после окончания выполнения задачи. То есть в первом случае мы имеем фиксированный интервал запуска задач, а во втором фиксированный интервал задержки между задачами.
  
  