Общество Мертвых Потоков
TRANSCRIPT
3
Чего не будет в презентации
• Определений из учебника- Больше интересует сама концепция
• Сравнения производительности• Советов, как правильно писать код• Холиваров*• Серебряных пуль, волшебных фреймворков и т.п.
* Нет, ну если кто-‐то очень захочет, то можно, конечно…
4
А что будет-то?
• Пара простых многопоточных примеров• Куча связанных с ними проблем• Варианты решений- Которые, разумеется, не работают
- Ну некоторые работают- Иногда
- Наверное…
5
Пререквизиты
Нужно примерно понимать, что такое• Thread• Runnable• synchonized• Lock lock = new ReentrantLock(false)• volatile• AtomicInteger• Compare-And-Set
6
Стенд
• Apple MacBook Pro Retina, 2014- Intel Core i7- 4 cores x 2 threads = 8 HW threads- 2,3 GHz
- 16 Gb RAM- Oracle JDK 8 update 60
• Mac OS X 10.10.5
8
• 5 философов по кругу– Тарелка с едой перед каждым– Вилки между тарелками
• Каждый может– Размышлять– Брать соседнюю вилку– Есть (строго двумя вилками!)– Класть одну вилку
Задача о философах
9
Проблемы с обедающими философами
Пусть каждый философ действует по некоторому алгоритму
• Могут ли все философы умереть с голоду?
• Можно ли составить такой алгоритм, чтобы все философы гарантированно не умерли с голоду?
10
Параметры задачи
• Количество философов• Есть ли возможность положить вилку, не пожрамши• Сколько времени философ ест- Фиксированное или случайная величина
• Сколько времени философ размышляет- Фиксированное или случайная величина- Как это время соотносится с временем еды
• Какие ещё инструменты/элементы есть в системе?• Что ещё?
11
Фиксированное время и случайное время
• Случайное время задаётся какой-‐то функцией распределения
• Константа тоже задаётся функцией распределения- (А бывают ли вообще константы в реальном мире?)
12
Фиксированное время и случайное время
• Случайное время задаётся какой-‐то функцией распределения
• Константа тоже задаётся функцией распределения- (А бывают ли вообще константы в реальном мире?)
16
Простое решение
• Когда философ хочет есть, он делает следующие шаги:1. Берёт левую от себя вилку («сено»)2. Берёт правую от себя вилку («солома»)3. Ест4. Кладёт одну вилку5. Кладёт другую вилку6. Размышляет
• И так по кругу
21
Ресурсы и взаимоблокировка
Ресурс – объект, к которому предоставляется доступ
Во время работы процесс может брать (захватывать) ресурсы
22
Взаимоблокировка (Deadlock)
Взаимоблокировка – такое состояние системы, при котором два или более процессов не могут продолжать своё выполнение из-‐за отсутствия необходимых для этого ресурсов.
Каждый ждёт другого, поэтому никто не может продолжить
23
Выгружаемые и невыгружаемые ресурсы
• Выгружаемые ресурсы — ресурсы, которые могут быть безболезненно отобраны у процесса, который ими обладает
• Невыгружаемые ресурсы — ресурсы, которые нельзяотобрать у процесса, не вызвав при этом сбой в вычислениях
• Мы будем говорить, в основном, о невыгружаемых ресурсах
24
Операции над невыгружаемыми ресурсами
• Запрос ресурса- Берём ресурс - или ждём (встаём в «очередь» ожидания)
• Использование ресурса• Освобождение ресурса
26
Условия возникновения взаимоблокировок
Коффман, 19711. Условие взаимного исключения2. Условие удержания и ожидания3. Условие невыгружаемости4. Условие циклического ожидания
27
Условие взаимного исключения
Каждый ресурс либо выделен в данный момент только одному процессу, либо доступен для всех.
28
Условие удержания и ожидания
Процессы, удерживающие в данный момент ранее выделенные им ресурсы, могут запрашивать новые ресурсы.
29
Условие невыгружаемости
Ранее выделенные ресурсы не могут быть принудительно отобраны у процесса.
Они должны быть явным образом высвобождены тем процессом, который их удерживает.
30
Условие циклического ожидания
Должна существовать кольцевая последовательность из двух и более процессов, каждый из которых ожидает высвобождения ресурса, удерживаемого следующим членом последовательности.
32
Моделирование взаимоблокировок
Ресурс занят Запрос ресурса Взаимоблокировка
Граф ожидания (Holt, 1972)
34
Условия возникновения взаимоблокировок —ещё раз
Коффман, 19711. Условие взаимного исключения2. Условие удержания и ожидания3. Условие невыгружаемости4. Условие циклического ожидания
37
Стратегии борьбы с блокировками
• Игнорирование проблемы• Обнаружение и восстановление• Динамическое уклонение• Предотвращение за счёт подавления любого из четырёх условий Коффмана
39
Кто использует стратегии борьбы?
• Базы данных- Блокировки на строках, таблицах, индексах и т.д.
• JVM
40
Кто использует стратегии борьбы?
• Базы данных- Блокировки на строках, таблицах, индексах и т.д.
• JVM- А вот и нет!- Ручками, ручками!
- Ну и головой…
41
Алгоритм Страуса
(Делаем вид, что проблема отсутствует)• Насколько часто возникает проблема?• Как часто возникают сбои в системе по другим причинам?
• Насколько серьёзны могут быть последствия?
42 Обнаружение взаимоблокировок и восстановление работоспособности
• Шаги- Позволить блокировке произойти- Пытаться обнаружить момент возникновения- Попробовать восстановить работоспособность
В нашем примере можно просто перезапускать философов
43
Выход из взаимоблокировки
• Приоритетный захват ресурсов- Приоритезировать (все) процессы- Отобрать ресурс у менее приоритетного процесса
• Откат (см. след. слайд)• Уничтожение и перезапуск процессов
44
Выход из взаимоблокировки — Откат
• Периодически создаются контрольные точки• При обнаружении блокировки происходит откат- При откате часть работы (которая была выполнена после прохождения последней контрольной точки) теряется
46
Уклонение от взаимоблокировки
• Алгоритм банкира (Дейкстра, 1965)• В основе — идея о траекториях
I, scheduler
48
Предотвращение взаимоблокировки
• Атака условия взаимного исключения• Атака условия ожидания и удержания• Атака условия циклического ожидания• Атака условия невыгружаемости
49
Атака условия взаимного исключения
• Возможна редко — часто программа становится некорректной
• Идея — убирать ненужные блокировки- Делать нужно осторожно, чтобы функциональность не страдала
- Заменять на другие механизмы
50
Атака условия ожидания и удержания
• Запрашивать ВСЕ необходимые ресурсы не в процессе работы, а до начала работы. - Но не всегда ресурсы известны заранее
• Вначале временно высвободить все удерживаемые ресурсы
52
Атака условия циклического ожидания
• Нумерация ресурсов!- Захватывать ресурсы только в порядке возрастания номеров
1
2 3
4
51
2
3
4
5
54
Голодание (Starvation)
• Голодание— ситуация, в которой поток, от которого ожидается прогресс, (практически) стоит на месте.
55
Голодание (Starvation)
• Голодание— ситуация, в которой поток, от которого ожидается прогресс, (практически) стоит на месте.
• Заблуждение- Голодание может осуществиться, только если потоки с более высоким приоритетом постоянно берут ресурсы, которые нужны голодающему потоку
60
Что же делать
• Решение с посредником: официант решает, кому можно брать вилку, а кому нет- Решение с общим критическим ресурсом- Решение с семафором
62
И все-таки бенчмарки…
5 потоков по 2 секунды
eat thinkOrdered Locks
Common Unfair Lock
Common Fair Lock Semaphore
0ms 0ms 25 000 000 55 000 000 450 000 11 000 0000ms 1ms 7 900 7 700 7 500 4 0001ms 0ms 1 600 1 500 1 500 1 7001ms 1ms 3 100 1 500 1 500 2 700
68
Модели
• Модель с разделяемой памятью- Регистры- Операции: read, write
- Удобно программировать, все привыкли• Модель с передачей сообщений- Послать сообщение- Похожа на то, как реально работает железо
71
Параллелизм — ОС
- Слушать музыку и переписыватьсяв фейсбуке в Одноклассниках
- При зависании одной программы другие продолжают работать
- и т.п.
72
Преимущества параллелизма
• Использование нескольких ядер/процессоров- Да и на 1 ядре тоже! (async I/O)
• Простота моделирования- Абстракция: фреймворк забирает сложность
• Упрощенная обработка асинхронных событий• Более отзывчивые интерфейсы пользователя- Event Dispatch Thread (EDT), async calls
73
Параллелизм на уровне отдельно взятой программы
• Эффективное использование ресурсов• Удобство, простота написания кода• Справедливость - Обработка запросов пользователей на серверах соцсети с одинаковым приоритетом
- Читатели и писатели- Fairness (честность)
77
Блокировки
• java.util.concurrent— since Java 5- Lock —> ReentrantLock- ReadWriteLock —> ReentrantReadWriteLock
- StampedLock — since Java 8• Synchronized method / section• wait() / notify() / notifyAll()
78
Блокировки
• java.util.concurrent— since Java 5- Lock —> ReentrantLock- ReadWriteLock —> ReentrantReadWriteLock
- StampedLock — since Java 8• Synchronized method / section• wait() / notify() / notifyAll()
Общее: ожидание
79
Проблемы блокировок
• Взаимоблокировки (Deadlocks)• Инверсия приоритетов• Надежность — вдруг владелец блокировки помрет?• Performance- Параллелизма в критической секции нет!- Владелец блокировки может быть вытеснен планировщиком
80
Закон Амдала
• α — часть общего объема вычислений, которую нельзя распараллелить
• 1-α — часть, которую можно распараллелить
• p — количество потоков
81
Закон Амдала
• α — часть общего объема вычислений, которую нельзя распараллелить
• 1-α — часть, которую можно распараллелить
• p — количество потоков
83
Классификация
• Без препятствий (Obstruction-‐Free) — поток совершает прогресс, если не встречает препятствий со стороны других потоков
• Без блокировок (Lock-‐Free)— гарантируется системный прогресс хотя бы одного потока
• Без ожидания (Wait-‐Free) — каждая операция выполняется за фиксированное число шагов, не зависящее от других потоков
84
Консенсус
• Объект consensus с операцией decide(v):- consensus.decide(v) ≠ const- wait-‐free
• N Потоков вызывают consensus.decide()- i-‐ый поток вызывает consensus.decide(vi)- Каждый поток вызывает не более 1 раза- decide() возвращает одно из vi
• decide() — протокол консенсуса
85
Консенсусное число
• Мощность консенсуса —максимальное количество (N) потоков, для которых данный объект обеспечивает консенсус
• Консенсусное число примитива синхронизации —максимальная мощность консенсуса, который можно построить на базе данного примитива и некоторого количества атомарных регистров- То есть, существует реализация метода decide для N потоков, использующая данный примитив как строительный блок
86
Консенсусные числа различных операций
• Операции на регистрах — 1• Read-‐Modification-‐Write (RMW) — 2- Common2 Class — коммутируют друг с другом или перезаписывают друг друга
- Универсальные операции —∞- Сравнение с обменом (CAS): Compare-‐And-‐Swap, Compare-‐And-‐Set
87
Compare and Swap
• Compare-and-swap (CAS)- IA32, x64 - SPARC
• load-linked / store-conditional (LL/SC)- PowerPC- ARM
89
CAS Loop — типичный паттерн применения
1. Прочитать значение A из переменной V2. Взять какое-‐то новое значение B для V3. Использовать CAS для атомарного изменения V из A
в B до тех пор, пока другие потоки меняют значение V во время этого процесса
Атомарность Read-‐Modify-‐Write реализуется за счет постоянного мониторинга системы на предмет постороннего вмешательства
91
Fast vs. slow path
• Каждый блок кода может иметь, как минимум, два пути исполнения: короткий и длинный
• Lock: contended vs. Uncontended• Uncontended Lock:- ≥ 1 CAS
92
Недостатки CAS
• CAS заставляет потоки, которые его вызывают, работать в условиях соревнования (contention)- Больше contention = больше бесполезных циклов процессора, трата процессорного времени
• Написание корректных и быстрых алгоритмов на CAS требует специальной подготовки
94
Поддержка CAS в Java
• В Java 5 появился JSR166- пакет java.util.concurrent- пакет java.util.concurrent.atomic
• На платформах, поддерживающих CAS, JIT-‐компилятор делает inline соответствующих машинных инструкций
• Load Linked / Store Conditional
95
Atomic variable classes
• Scalars• Field updaters• Arrays• Compound variables• Accumulators- since Java 8
97
AtomicInteger
• boolean compareAndSet(int expect, int update)• int addAndGet(int delta)• int getAndDecrement()• int getAndIncrement()• int incrementAndGet()• …
98
AtomicInteger
• boolean compareAndSet(int expect, int update)• int addAndGet(int delta)• int getAndDecrement()• int getAndIncrement()• int incrementAndGet()• …
Эти операции — блокирующие?
101
Field Updaters
• AtomicIntegerFieldUpdater- Reflection-‐based updater for volatile int
• AtomicLongFieldUpdater- Reflection-‐based updater for volatile long
• AtomicReferenceFieldUpdater
- Reflection-‐based updater for volatile object
102
AtomicLongFieldUpdater
- long addAndGet(T obj, long delta)
- boolean compareAndSet(T obj, long expect, long update)
- long getAndAdd(T obj, long delta)
- long incrementAndGet(T obj)
106
AtomicLongArray
• long addAndGet(int i, long delta)• long getAndAdd(int i, long delta)• boolean compareAndSet(int i, long expect, long update)
• long incrementAndGet(int i)• …
107
Compound Variables
• AtomicMarkableReference- compareAndSet(V expectedReference, V newReference,boolean expectedMark, boolean newMark)
• AtomicStampedReference- boolean compareAndSet(V expectedReference, V newReference, int expectedStamp, int newStamp)
110
• Алгоритм называется неблокирующим (nonblocking), если отказ или остановка любого потока не может привести к отказу или остановке любого другого потока
• Алгоритм называется свободным от блокировок (lock-‐free), если на каждом шаге какой-‐то поток выполняет работу (make progress)
• nonblockingи lock-‐free — это разные вещи!- Алгоритмы на CAS могут быть одновременно неблокирующими и свободными от блокировок
110
Неблокирующие алгоритмы
119
DL и все-все-все
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-‐interest
To post a message to all the list members, send email toconcurrency-‐[email protected]