nonblocking algorithms/cas/atomics by alexey fyodorov

Post on 16-Apr-2017

155 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Алексей  Федоров,  Одноклассники  / JUG.ru

Атомики,  CAS  и  неблокирующие  алгоритмы

Зачем  вы  здесь?

3

4Модели

• Модель  с  разделяемой  памятью- Регистры

- Операции:  read,  write- Удобно  программировать,  все  привыкли

• Модель  с  передачей  сообщений- Послать  сообщение- Похожа  на  то,  как  реально  работает  железо

5Терминология

• Нет  устоявшейся  терминологии• Термины:• Parallel

- Concurrent- Distributed

6Виды  параллелизма

• На  уровне  операционной  системы• На  уровне  одной  программы  /  процесса

7Параллелизм  — ОС

• Слушать  музыку  и  переписываться  в  фейсбуке в  Одноклассниках

• При  зависании  одной  программы  другие  продолжают  работать

• и  т.п.

8Преимущества  параллелизма

• Использование  нескольких  ядер/процессоров- Да  и  на  1  ядре  тоже!  (async I/O)

• Простота  моделирования- Абстракция:  фреймворкзабирает  сложность

• Упрощенная  обработка  асинхронных  событий

• Более  отзывчивые  интерфейсы  пользователя- Event  Dispatch  Thread  (EDT),  async calls

9Параллелизм  на  уровне  отдельно  взятой  программы

• Эффективное  использование  ресурсов• Удобство,  простота  написания  кода• Справедливость  

- Обработка  запросов  пользователей  на  серверах  соцсети с  одинаковым  приоритетом

- Читатели  и  писатели- Fairness  (честность)

10

Lock lock = new ReentrantLock(true);

11Честность!

Lock lock = new ReentrantLock(true);

12Блокировки

• java.util.concurrent — since  Java  5- Lock  —>  ReentrantLock- ReadWriteLock —>  ReentrantReadWriteLock- StampedLock — since  Java  8

• Synchronized  method  /  section• wait()  /  notify()  /  notifyAll()

13Блокировки

• java.util.concurrent — since  Java  5- Lock  —>  ReentrantLock- ReadWriteLock —>  ReentrantReadWriteLock- StampedLock — since  Java  8

• Synchronized  method  /  section• wait()  /  notify()  /  notifyAll()

Общее: ожидание

14Проблемы  блокировок

• Взаимоблокировки  (Deadlocks)• Инверсия  приоритетов• Надежность  — вдруг  владелец  блокировки  помрет?• Performance

- Параллелизма  в  критической  секции  нет!- Владелец  блокировки  может  быть  вытеснен  

планировщиком

15Закон  Амдала

• α — часть  общего  объема  вычислений,  которую  нельзя  распараллелить  

• 1-α — часть,  которую  можно  распараллелить

• p — количество  потоков

16Закон  Амдала

• α — часть  общего  объема  вычислений,  которую  нельзя  распараллелить  

• 1-α — часть,  которую  можно  распараллелить

• p — количество  потоков

Неблокирующие  алгоритмы

18Классификация

• Без  препятствий  (Obstruction-­‐Free)  — поток  совершает  прогресс,  если  не  встречает  препятствий  со  стороны  других  потоков

• Без  блокировок  (Lock-­‐Free)— гарантируется  системный  прогресс  хотя  бы  одного  потока

• Без  ожидания (Wait-­‐Free)—каждая  операция  выполняется  за  фиксированное  число  шагов,  не  зависящее  от  других  потоков

19Консенсус

• Объект  consensus  с  операцией  decide(v):- consensus.decide(v)  ≠  const- wait-­‐free

• N  Потоков  вызывают  consensus.decide()- i-­‐ый поток  вызывает  consensus.decide(vi)- Каждый  поток  вызывает  не  более  1  раза- decide() возвращает  одно  из  vi

• decide()  — протокол  консенсуса

20Консенсусное число

• Мощность  консенсуса  — максимальное  количество  (N) потоков,  для  которых  данный  объект  обеспечивает  консенсус

• Консенсусное число  примитива  синхронизации  —максимальная  мощность  консенсуса,  который  можно  построить  на  базе  данного  примитива и  некоторого  количества  атомарных  регистров- То  есть,  существует  реализация  метода  decide  для  N  потоков,  

использующая  данный  примитив  как  строительный  блок

21Консенсусные числа  различных  операций

• Операции  на  регистрах  — 1• Read-­‐Modification-­‐Write  (RMW)— 2

- Common2  Class— коммутируют  друг  с  другом  или  перезаписывают  друг  друга

- Универсальные  операции  —∞- Сравнение  с  обменом  (CAS):  

Compare-­‐And-­‐Swap,  Compare-­‐And-­‐Set

22Compare  and  Swap

• Compare-­‐and-­‐swap  (CAS)- IA32,  x64  - SPARC

• load-­‐linked  /  store-­‐conditional  (LL/SC)- PowerPC- ARM

23Семантика  CAS

24CAS  Loop  — типичный  паттерн  применения

1. Прочитать  значение  A  из  переменной  V2. Взять  какое-­‐то  новое  значение  B  для  V3. Использовать  CAS  для  атомарного  изменения  V  из  A  в  B до  тех  

пор,  пока  другие  потоки  меняют  значение  V  во  время  этого  процесса

Атомарность Read-­‐Modify-­‐Write  реализуется  за  счет  постоянного  мониторинга системы  на  предмет  постороннего  вмешательства

25Пример:  неблокирующий  счетчик

26Fast  vs.  slow  path

• Каждый  блок  кода  может  иметь,  как  минимум,  два  пути  исполнения:  короткий  и  длинный

• Lock:  contended  vs.  Uncontended

• Uncontended  Lock:- ≥  1  CAS

27Недостатки  CAS

• CAS  заставляет  потоки,  которые  его  вызывают,  работать  в  условиях  соревнования  (contention)- Больше  contention  =  больше  бесполезных  циклов  

процессора,  трата  процессорного  времени

• Написание  корректных  и  быстрых  алгоритмов  на    CAS  требует  специальной  подготовки

Поддержка  в  Java

29Поддержка  CAS  в  Java

• В  Java  5  появился  JSR166- пакет  java.util.concurrent- пакет  java.util.concurrent.atomic

• На  платформах,  поддерживающих  CAS,  JIT-­‐компилятор  делает  inline  соответствующих  машинных  инструкций

• Load  Linked  /  Store  Conditional  

30Atomic  variable  classes

• Scalars• Field  updaters• Arrays• Compound  variables• Accumulators

- since  Java  8

31Scalars

• AtomicBoolean• AtomicInteger• AtomicLong• AtomicReference

32AtomicLong

• boolean compareAndSet(int expect,  int update)• long  addAndGet(int delta)• long getAndAdd(int delta)• long  getAndDecrement()• long  getAndIncrement()• long  incrementAndGet()• …

33AtomicLong

• boolean compareAndSet(int expect,  int update)• long  addAndGet(int delta)• long getAndAdd(int delta)• long  getAndDecrement()• long  getAndIncrement()• long  incrementAndGet()• …

34

35

atomicLong.getAndAdd(5)

loop:mov 0x10(%rbx),%raxmov %rax,%r11add        $0x5,%r11lock  cmpxchg  %r11,0x10(%rbx)sete      %r11bmovzbl  %r11b,%r11dtest %r10d,%r10dje          loop

JDK  7u80        -­‐XX:+PrintAssembly

36

atomicLong.getAndAdd(5)

lock  addq $0x5,0x10(%rbp))loop:mov 0x10(%rbx),%raxmov %rax,%r11add        $0x5,%r11lock  cmpxchg  %r11,0x10(%rbx)sete      %r11bmovzbl  %r11b,%r11dtest %r10d,%r10dje          loop

JDK  7u80        -­‐XX:+PrintAssembly JDK  8u60   -­‐XX:+PrintAssembly

37

atomicLong.getAndAdd(5)

lock  addq $0x5,0x10(%rbp))loop:mov 0x10(%rbx),%raxmov %rax,%r11add        $0x5,%r11lock  cmpxchg  %r11,0x10(%rbx)sete      %r11bmovzbl  %r11b,%r11dtest %r10d,%r10dje          loop

JDK  7u80        -­‐XX:+PrintAssembly JDK  8u60   -­‐XX:+PrintAssembly

83

46

15 11

132105

45 43

1 2 3 4

ops  /  μs

threads

38

39Multivariable   Invariant

40Multivariable   Invariant

41Field  Updaters

• AtomicIntegerFieldUpdater- Reflection-­‐based  updater  for  volatile  int

• AtomicLongFieldUpdater- Reflection-­‐based  updater  for  volatile  long

• AtomicReferenceFieldUpdater

- Reflection-­‐based  updater  for  volatile  object

42AtomicLongFieldUpdater

long  addAndGet(T  obj,  long  delta)

boolean compareAndSet(T  obj,  long  exp, long  upd)

long  getAndAdd(T  obj,  long  delta)

long  incrementAndGet(T  obj)

Demo.  Legacy  Volatile  Counter

44AtomicLongFieldUpdater

45AtomicLongFieldUpdater

46AtomicArrays

• AtomicIntegerArray

• AtomicLongArray

• AtomicReferenceArray

47AtomicLongArray

• long  addAndGet(int i,  long  delta)

• long  getAndAdd(int i,  long  delta)

• boolean compareAndSet(int i,  long  exp,  long  upd)

• long  incrementAndGet(int i)

• …

48Compound  Variables

AtomicMarkableReferenceV  compareAndSet(

V  expectedRef,  V  newRef,  boolean expectedMark,  boolean newMark)

AtomicStampedReferenceboolean compareAndSet(

V  expectedRef,  V  newRef,  int expectedStamp,  int newStamp)

49Accumulators

• DoubleAccumulator

• DoubleAdder

• LongAccumulator

• LongAdder

• (Striped64)

50LongAccumulator

• void  accumulate(long  x)

• long  get()

• long  getThenReset()

• Void  reset()

51

• Алгоритм  называется  неблокирующим  (nonblocking),  если  отказ  или  остановка  любого  потока  не  может  привести  к  отказу  или  остановке  любого  другого  потока

• Алгоритм  называется  свободным  от  блокировок (lock-­‐free),  если  на  каждом  шаге  какой-­‐то  поток  выполняет  работу  (make  progress)

51

Неблокирующие  алгоритмы

52

• Алгоритм  называется  неблокирующим  (nonblocking),  если  отказ  или  остановка  любого  потока  не  может  привести  к  отказу  или  остановке  любого  другого  потока

• Алгоритм  называется  свободным  от  блокировок (lock-­‐free),  если  на  каждом  шаге  какой-­‐то  поток  выполняет  работу  (make  progress)

• nonblockingи  lock-­‐free  — это  разные  вещи!- Алгоритмы  на  CAS  могут быть  одновременно  неблокирующими  и  

свободными  от  блокировок  

52

Неблокирующие  алгоритмы

53Неблокирующий  стек

54Неблокирующий  стек

55Неблокирующий  стек

56Неблокирующая  очередь

• Michael  and  Scott,  1996• Потоки  помогают друг  другу

Литература

58

59

60

61DL  и  все-­все-­все

http://altair.cs.oswego.edu/mailman/listinfo/concurrency-­‐interest

To  post  a  message  to  all  the  list  members,  send  email toconcurrency-­‐interest@cs.oswego.edu

62Много  полезных  видео

63

https://bitbucket.org/23derevo/concurrency

Вопросы  и  ответы

Спасибо  за  внимание!

@23derevoalexey@jugru.orgalexey.fyodorov@corp.mail.ru

top related