Core-2: Concurrency Flashcards

1
Q

Что такое многопоточность?

A

Concurrency - Принцип построения программы, при котором несколько блоков кода могут выполняться одновременно.
В одноядерном процессоре: Context Switch
В многоядерном процессоре: Context Switch + Parallelism

Синхронно - последовательно
Асинхронно - параллельно

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Что такое и чем процесс отличается от потока? (4)

A

Процесс - это экземпляр программы, создаваемый и исполняемый операционной системой.

Поток - подпроцесс, определяющий последовательность исполнения кода в процессе.
Поток: new-> runnable(ready/running)-> terminated.
JVM, испоняющая байткод - процесс, а GC в ней - поток

Различия:
1) Процессы - независимые сущности, существующие в своем адресном пространсве, потоки существуют в рамках адресного пространства содеращего процесса.
2) процесс не может напрямую обращаться к ресурсам другого П.,
процессы обмениваются данными через конвейеры, файлы, каналы связи между компьютерами и многое другое.
Поток может обращаться ко всем ресурсам содержащего прцесса.
3) Процесс гораздо тяжелее потока, его запуск и содержание обходится гораздо дороже.
4) Потоки подходят для параллелизации задач в рамках процесса, процессы служат для параллельно исполнения взаимонезависимых задач.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Что такое потоки-демоны?

A

В отличии от пользовательских потоков, которые явно создаются пользователем, демоны создаются системой для обеспечения вспомогательных действий (garbage collector)
JVM принудительно завершит всех демонов, когда будет завершён последний пользовательский поток.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Чем Thread отличается от Runnable? Когда нужно использовать Thread, а когда Runnable?
(Ответ что тред - это класс, а ранбл интерфейс - считается не
полным, нужно рассказать подробно)

A

Runnable – это функциональный интерфейс с единственным методом public void run(). Экземпляр R. не является потоком, а просто формулирует задачу, которую можно выполнить в отдельном потоке.
Thread implements Runnable – это класс, содержащий методы для запуска и управления состоянием потока, экземпляр которого мы можем создать и запустить в отдельном потоке, переопределив метод run()->Thread implements Runnable.

Чтобы использовать несколько потоков мы можем:
~~~
Class MyThread extends Thread{
@Override public void run(){sout(“new thread strarts”);}
psvm{
MyThread myThread = new MyThread();
myThread.strart();}}
or
Class MyRunnable implements Runnable{
@Override public void run(){sout(“new thread strarts”);}}
psvm{
// myRunnable- описание задачи, которая может быть исполнена в myThread:
MyRunnable myRunnable = new MyRunnable();
// myThread - исполняемая сущность класса Thread:
Thread myThread = new Thread(myRunnable);
myThread.strart();}
~~~

1) extend Thread избавляет от лишней строчки при создании экземпляра Thread, а implement Runnable позволяет классу наследоваться от другого класса, кроме Thread.
2) runnuble позволяет отделить логику выполнения задачи от непосредственного управления потоком, так как экз. R. - задача, которую может исполнить поток, и ей нет дела до того, как именно организована работа этого потока.
3) Есть практика, что если нет необходимости переопределятьу Thread что-то кроме run(), то лучше implement Runnable.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Что такое монитор? Как монитор реализован в java?

A

Монитор – механизм синхронизации потоков, обеспечивающий упорядоченный доступ к общим ресурсам по принципу mutex (mutual exclusion).
Монитор встроен в класс Object и имеется у каждого объекта или класса. Он имеет 2 состояния: занят и свободен.
В Java монитор реализован с помощью ключевого слова synchronized, причем ни методы ни блоки не имеют монитора, используется монитор this в методе неявно, и в блоке явно. в static class используется монитор класса.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Что такое синхронизация? Какие способы синхронизации существуют в java?

A

Синхронизация – это процесс, который позволяет выполнять потоки параллельно:
все объекты имеют блокировку, благодаря которой только один поток одновременно может получить доступ к критическому коду в объекте.

Способы:
1. Системная синхронизация с использованием wait()/notify().
wait - освобождает монитор и переводит вызывающий поток в состояние ожидания, пока другой поток не вызовет notify() или не истечет время в параметре: wait(1000 ms)
notify - не освобождает монитор, но “будит” один спящий или ожидающий поток и позволяет ему поучаствовать в битве за монитор.
NB: оба этих метода надо вызывать на том объекте, на котором мы делаем синхронизацию (чей монитор используется).
NB2: условие для вызова wait должно проверяться в while() что позволяет перепроверить условие, т.к. в редких случаях поток может проснуться без notify()

  1. Системная синхронизация с использованием join():
    поток, внутри которого вызван join() дождется выполнения потоков на которые вызван этот join(), либо пока не пройдет время указанное в параметрах join(100 ms):
    psvm { // some code; otherThread.start(); otherThread.join(); // some code;} - поток main дождется пока отработает otherThread и только потом продолжит работу.
  2. Использование классов из пакета java.util.concurrent.Locks – механизмы
    синхронизации потоков, альтернативы базовым synchronized, wait, notify, notifyAll: Lock, Condition, ReadWriteLock.
    Lock lock = new ReentrantLock(); lock.lock() // lock.tryLock()=> code =>finally { lock.unlock();}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Что обозначает ключевое слово volatile? Почему операции над volatile
переменными не атомарны?

A

volatile запрещает копировать значение переменной в в кэш потока, т.о. она хранится только в хипе.
volatile атомарна для чтения, но не для записи и имеет смысл только когда лишь 1 поток пожет изменить значение переменной, остальные только читают
чтение(1), изменение(2) в запись(3) - другой поток может вклиниться между этими этапами.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Для чего нужны Atomic типы данных? Чем отличаются от volatile?

A

volatile не гарантирует атомарность. Например, операция count++ не станет атомарной просто потому, что count объявлена volatile.
C другой стороны, class AtomicInteger предоставляет атомарный метод для выполнения таких комплексных операций атомарно, например getAndIncrement() – атомарная замена оператора инкремента, его можно использовать, чтобы атомарно увеличить текущее значение на один.
Похожим образом сконструированы атомарные версии и для других типов данных.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Как устроен Increment в Atomic?

A

Для обеспечения целостности данных используется низкоуровневая инструкциия CAS (compare-and-swap), которая на машинном уровне объединяет 3 операции в одну атомарную.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Чем Runnable отличается от Callable?

A

Callable<T> как и Runnable представляет собой определенное задание, которое выполняется потоком, но
- Callable<T>: V call() throws Exception; || Runnable: void run()
- имеет return type не void
- throws Exception
- Callable параметризован: call() возвращает T или Object, если не параметризовать.
- Callable работает только с ExecutorService, R. и с ним и с Thread;</T></T>

Future<T> = содержит будущий результат работы потока, и get() на нем вызовется только когда поток завершит работу.</T>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Что такое Thread Pool и ExecutorService?

A

ТР - Множество потоков, каждый из которых выполняет ту или иную задачу.
Создавать лучше через Executors.newFixedThreadPool(5);
ES - создает ТР и передает в него задачи.
метод execute(runnable r) / submit(callable c) from ExService передает задачу в ТР

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Что такое FutureTask? (5)

A

FutureTask - отменяемое асинхронное вычисление.
Этот класс предоставляет базовую реализацию Future с методами для запуска, остановки, запроса состояния и извлечения результатов вычисления.

Результат может быть получен, только когда вычисление завершено, метод получения будет заблокирован, если вычисление еще не завершено.
Объекты FutureTask могут быть использованы для обертки объектов Callable и Runnable.
Так как FutureTask помимо Future реализует Runnable, его можно передать в Executor на выполнение.
~~~
Future<Integet> future = executorService.submit(callable c);
(future.cancel() / future.get() / future.isCancelled() / future.isDone())
~~~</Integet>

Если мы передадим в submit() runnable - future будет null, однако другие методы сработают.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Что такое deadlock?

A

Взаимная блокировка (deadlock) – явление, при котором все потоки находятся в режиме ожидания и ничего не делают.
Может произойти, когда соблюдаются все условия:
* взаимное исключение: по крайней мере один ресурс занят в syncronized режиме, и следовательно только один поток может использовать его в конкретный момент;
* удержание и ожидание: поток уже удерживает ресурс и запрашивает дополнительные syncronized ресурсы, которые могут удерживаються другими потоками;
* цикличного ожидания: поток ждет освобождения ресурса другим потоком, который в свою очередь ждет освобождения ресурса заблокированного первым потоком.
* отсутствия предочистки: операционная система не может отбирать ресурсы у процесса;

Простейший способ избежать взаимной блокировки – не допускать цикличного ожидания. Этого можно достичь, если все потоки получают мониторы в одинаковом определенном порядке и освобождают их в обратном порядке.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Что такое livelock?

A

livelock – тип взаимной блокировки, при котором несколько потоков залочены навсегда, ожидают друг друга, проделывая работу буз прогресса.
Часто возникает в результате попыток предотвращения deadlock.
Узнать о наличии livelock можно, например, проверив уровень загрузки процессора в состоянии покоя.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Что такое race condition?

A

Состояние гонки возникает вследствии ошибки проектирования, когда несколько потоков имеют доступ к общим ресурсам и данным и порядок этого доступа хаотичен.
Допущение состояния гонки является причиной:
Data Race - ситуация, когда несколько потоков имеют доступ к переменной и хотябы один из них может ее изменить..
Lock Starvation – потоки не заблокированы, но есть нехватка ресурсов, из-за чего менее преоритетные потоки ждут либо очень долго, либо вечно.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Что такое Фреймворк fork/join? Для чего он нужен?

A

Фреймворк Fork/Join, представленный в JDK 7, – это набор классов и интерфейсов, позволяющих использовать преимущества многопроцессорной архитектуры современных компьютеров.
В его основе лежит ForkJoinPool: имплементация ExecutorService, которая не создает отдельный поток под каждую подзадачу, а создает для каждого потока Queue или Deque с подзадачами. В частности это помогает реализовать ключевой алгоритма фреймворка:
workstealing - потоки, которые завершили выполнение собственных подзадач, могут «украсть» подзадачи у других потоков, которые все еще заняты.

Этап Fork: большая задача разделяется на несколько меньших подзадач, которые в свою очередь также разбиваются на меньшие. И так до тех пор, пока задача не становится тривиальной и решаемой последовательным способом.
Этап** Join**: далее (опционально) идет процесс «свертки» – решения подзадач некоторым образом объединяются, пока не получится решение всей задачи.

Решение всех подзадач (в т. ч. и само разбиение на подзадачи) происходит параллельно.

Для решения некоторых задач этап Join не требуется. Например, для параллельного QuickSort – массив рекурсивно делится на все меньшие и меньшие диапазоны, пока не вырождается в тривиальный случай из 1 элемента. Хотя в некотором смысле Join будет необходим и тут, т. к. все равно остается необходимость дождаться, пока не закончится выполнение всех подзадач.

17
Q

Какя связь у Stream API и Fork/Join?

A

Stream API может использовать Fork/Join Framework для распараллеливания операций над коллекциями данных. Например, при вызове метода parallelStream() на коллекции, Stream API автоматически использует Fork/Join Framework для распределения задач между потоками. Это позволяет ускорить выполнение операций над большими коллекциями данных и повысить производительность приложения.

18
Q

Что означает ключевое слово synchronized? Где и для чего может
использоваться?

A

позволяет добиваться синхронизации в помеченных им методах
или блоках кода: потоки могут заходить в него только по очереди.

19
Q

Как синхронизировать несколько методов?

A

Синхронизировать их по монитору одного объекта.

20
Q

Что является монитором у статического синхронизированного метода?

A

Объект типа Class, соответствующий классу, в котором определен метод.

21
Q

Что является монитором у нестатического синхронизированного метода?

A

Объект this.

22
Q

util. Concurrent поверхностно. (7)

A

Since 1.5
Классы и интерфейсы пакета java.util.concurrent можно объединить в несколько групп по функциональному признаку:
- collections: набор эффективно работающих в многопоточной среде коллекций (CopyOnWriteArrayList/Set, ConcurrentHashMap, …)

CopyOnWriteArrayList:
* volatile массив внутри;
* при создании итератора нам возвращается неизменяемый оттиск листа для чтения, а при изменении создается полная копия листа: такой механизм предотвращает ConcurrentModificationException
* fail-fast итератор;
* модификация через iterator невозможна – UnsupportedOperationException.
* lock только при модификации списка, поэтому операции чтения очень быстрые;
ConcurrentHashMap:
- volatile entries
- усложнилась hash функция
- сегментация: сегмент - класс, группа HashMap’ов. Количество сегментов по умолчанию равно 16. Если пара key-value хранится в 10-ом сегменте, то ConcurrentHashMap заблокирует при необходимости только 10-й сегмент, и не будет блокировать остальные 15.

synchronizers – объекты синхронизации, позволяющие разработчику управлять и/или ограничивать работу нескольких потоков. Cодержит пять объектов синхронизации:
semaphore, countDownLatch, ciclycBarrier, exchanger, phaser.
Semaphore как Lock, но допускает несколько потоков в общий ресурс.
СountDownLatch - все потоки ждут, пока не выполнятся операции.
Exchanger - позволяет потокам обмениваться инфой, гарантируя одновременность её получения обоими.

atomic – набор атомарных классов для выполнения атомарных операций. Операция является атомарной, если ее можно безопасно выполнять при параллельных вычислениях в нескольких потоках, не используя при этом ни блокировок, ни синхронизацию synchronized.

Queues содержит классы формирования неблокирующих и блокирующих очередей для многопоточных приложений. Неблокирующие очереди «заточены» на скорость выполнения, блокирующие очереди приостанавливают потоки при работе с очередью.

Locks – механизмы синхронизации потоков, альтернативы базовым synchronized, wait, notify, notifyAll: Lock, Condition, ReadWriteLock.

Executors включает средства, называемые сервисами исполнения, позволяющие управлять потоковыми задачами с возможностью получения результатов через интерфейсы Future и Callable.

ExecutorService служит альтернативой классу Thread, предназначенному для управления потоками. В основу сервиса исполнения положен интерфейс Executor, в котором определен один метод:
void execute(Runnable thread);
При вызове метода execute исполняется поток thread.