86
Алексей Федоров, Одноклассники Синхронизация без блокировок и СМС

Алексей Федоров

Embed Size (px)

Citation preview

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

Синхронизация без блокировок и СМС

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

3

4Concurrency

5Concurrency

6 Много интересных докладов в других залах

7

Новичкам в области многопоточности

SorryПерейдите в другой зал

8

Новичкам в области многопоточности

SorryПерейдите в другой зал

Новичкам в неблокирующей синхронизации

Короткое введение

9

Новичкам в области многопоточности

SorryПерейдите в другой зал

Новичкам в неблокирующей синхронизации

Короткое введение

Продвинутым многопоточным программистам

Поговорим о деталях реализации CAS/atomics!

10

Новичкам в области многопоточности

SorryПерейдите в другой зал

Новичкам в неблокирующей синхронизации

Короткое введение

Продвинутым многопоточным программистам

Поговорим о деталях реализации CAS/atomics!

Хипстерам Поговорим про хайп!Immutable vs. Mutable

11Модели

• Модельсразделяемойпамятью- Операциинаатомарныхрегистрах:read,write- Удобнопрограммировать,всепривыкли

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

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

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

• Термины:- Parallel- Concurrent- Distributed

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

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

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

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

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

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

• ит.п.

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

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

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

• Упрощеннаяобработкаасинхронных событий• Болееотзывчивые интерфейсыпользователя- EventDispatchThread(EDT),async calls

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

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

- Читателииписатели

- Fairness(честность)

17

Lock lock = new ReentrantLock(true);

18Честность!

Lock lock = new ReentrantLock(true);

19 Блокировки

Old Schoolwait()notify()notifyAll()

synchronized {doSomething();

}

public synchronized foo() {doSomethingElse();

}

Вязыке

20 Блокировки

Old Schoolwait()notify()notifyAll()

synchronized {doSomething();

}

public synchronized foo() {doSomethingElse();

}Lock lock = new ReentrantLock();try {

lock.lock();doSomething();

} finally {lock.unlock();

}

Вязыке Вбиблиотеке(JDK)

java.util.concurrent.*java.util.concurrent.atomic.*

21Counter

public interface Counter {

long get();

void increment();

}

22Simple Counter

public class SimpleCounter implements Counter {

long value = 0;

public long get() {return value;

}

public void increment() {value++;

}

}

23Volatile Counter

public class VolatileCounter implements Counter {

volatile long value = 0;

public long get() {return value;

}

public void increment() {value++;

}

}

24 Synchronized Counter

public class SynchronizedCounter implements Counter {

long value = 0;

public synchronized long get() {return value;

}

public synchronized void increment() {value++;

}

}

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

• Взаимоблокировки (Deadlocks)

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

• Взаимоблокировки (Deadlocks)

• Инверсия приоритетов

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

• Взаимоблокировки (Deadlocks)

• Инверсия приоритетов

• Надежность — вдруг владелец блокировки помрет?

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

• Взаимоблокировки (Deadlocks)

• Инверсия приоритетов

• Надежность — вдруг владелец блокировки помрет?

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

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

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

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

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

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

Sp=𝟏

α#𝟏%α𝐩

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

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

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

Нам нужно что-то другое

Добро пожаловать в неблокирующую синхронизацию!

33If-Modify-Write

volatile int value = 0;

if (value == 0) {value = 42;

}

NoAtomicityintermsofJMM

34Compare and Swap

int value = 0;

synchronized (...) {if (value == 0) {

value = 42;}

}

35Введем волшебную операцию

int value = 0;

i.compareAndSet(0, 42);

36CompareandSwap— HardwareSupport

compare-and-swapCAS

load-link / store-conditionalLL/SC

cmpxchg

ldrex/strex lwarx/stwcx

37 CAS Semanticspublic class PseudoCAS {

private long value;

public synchronized long get() { return value; }

public synchronized long compareAndSwap(long expected, long newV) {long oldValue = value;if (oldValue == expected) {

value = newV;}return oldValue;

}

public synchronized boolean compareAndSet(long expected, long newV){return expected == compareAndSwap(expected, newV);

}}

38 Pseudo-CAS Counter

public class PseudoCasLoopCounter implements Counter {

private PseudoCAS value = new PseudoCAS();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}}

39 Pseudo-CAS Counter

public class PseudoCasLoopCounter implements Counter {

private PseudoCAS value = new PseudoCAS();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}}

CAS in Java

41CAS in Java

Since Java 5, JSR166

java.util.concurrent.atomic

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

since Java 8

42Scalars

• AtomicBoolean

• AtomicInteger

• AtomicLong

• AtomicReference

43Scalars

• AtomicBoolean

• AtomicInteger

• AtomicLong

• AtomicReference

44

• boolean compareAndSet(long expect, long update)

• long addAndGet(long delta)

• long getAndAdd(long delta)• long getAndDecrement()• long getAndIncrement()• long incrementAndGet()• …

AtomicLong

45

• boolean compareAndSet(long expect, long update)

• long addAndGet(long delta)

• long getAndAdd(long delta)• long getAndDecrement()• long getAndIncrement()• long incrementAndGet()• …

AtomicLong

46 CAS Counter

public class CasLoopCounter implements Counter {

private AtomicLong value = new AtomicLong();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}

}

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

Contended CAS —> tons of useless CPU cycles

do {v = value.get();

} while (value.compareAndSet(v, v + 1));

Написание быстрых и корректных алгоритмов на CAS требует экспертизы

48AtomicLong

• boolean compareAndSet(long expect, long update)

• long addAndGet(long delta)

• long getAndAdd(long delta)• long getAndDecrement()• long getAndIncrement()• long incrementAndGet()• …

49Get-and-Add Counter

public class CasLoopCounter implements Counter {

private AtomicLong value = new AtomicLong();

public long get() {return value.get();

}

public void increment() {value.getAndAdd(1);

}

}

50atomicLong.getAndAdd(5)

JDK7u95 JDK8u72

60

9 7 6

100

27 27 27

1 2 3 4

ops/μs

threads

51atomicLong.getAndAdd(5)

JDK7u95 JDK8u72

60

9 7 6

100

27 27 27

1 2 3 4

ops/μs

threads

52atomicLong.getAndAdd(5)

JDK7u95 JDK8u72

60

9 7 6

100

27 27 27

1 2 3 4

ops/μs

threads

53

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

JDK7u95-XX:+PrintAssembly

atomicLong.getAndAdd(5)

54

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

JDK7u95-XX:+PrintAssembly JDK8u77-XX:+PrintAssembly

atomicLong.getAndAdd(5)

JDK7u95 JDK8u72

60

9 7 6

100

27 27 27

1 2 3 4

ops/μs

threads

55 AtomicLong.getAndAdd()— JDK7

56 AtomicLong.getAndAdd()— JDK7

cmpxchg

57 AtomicLong.getAndAdd()— JDK8

58 AtomicLong.getAndAdd()— JDK8

lock addqJVMIntrinsic

59

counterType Cnt Score Error UnitsLONG 5 211.247 ± 7.532 ops/usVOLATILE_LONG 5 24.837 ± 1.664 ops/usALFU 5 27.272 ± 1.946 ops/usSYNCHRONIZED 5 10.231 ± 0.592 ops/usUNFAIR_LOCK 5 19.959 ± 4.268 ops/usFAIR_LOCK 5 0.225 ± 0.009 ops/usCAS_LOOP 5 6.125 ± 0.225 ops/usADD_AND_GET 5 26.701 ± 0.620 ops/us

Бенчмарки!

Thanks to Nitsan Wakarthttp://psy-lob-saw.blogspot.ru/2014/06/jdk8-update-on-scalable-counters.html

Core(TM) i7-47704 x 2 x 1.9 Ghz(downgraded)

Ubuntu 14.04.33.13.0-83-genericx86_64taskset -c 0,1,2,3(thread affinity)

60Multivariable Invariant

61 Multivariable Invariant

62 Field Updaters

• AtomicIntegerFieldUpdater

– Reflection-based updater for volatile int

• AtomicLongFieldUpdater

– Reflection-based updater for volatile long

• AtomicReferenceFieldUpdater

– Reflection-based updater for volatile object

63AtomicLongFieldUpdater

long addAndGet(T obj, long delta)

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

long getAndAdd(T obj, long delta)

long incrementAndGet(T obj)

64VolatileCounter

public class VolatileCounter implements Counter {

volatile long value = 0;

public long get() {return value;

}

public void increment() {value++;

}

}

65VolatileCounter

public class VolatileCounter implements Counter {

volatile long value = 0;

public long get() {return value;

}

public void increment() {value++;

}

}

66 AtomicLongFieldUpdater-based Counterprivate final VolatileCounter counter = new VolatileCounter();

ALFU<VolatileCounter> updater= ALFU.newUpdater(VolatileCounter.class, "value");

public AFUCounter() throws NoSuchFieldException {Field field = VolatileCounter.class.getDeclaredField("value");field.setAccessible(true);

}

public long get() { return updater.get(counter);

}

public void increment() { updater.addAndGet(counter, 1);

}

67AtomicLongFieldUpdater

68AtomicLongFieldUpdater

69AtomicArrays

AtomicIntegerArray

AtomicLongArray

AtomicReferenceArray

long addAndGet(int i, long delta)

long getAndAdd(int i, long delta)

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

long incrementAndGet(int i)

70 Compound Variables

AtomicMarkableReference V сompareAndSet (V expectedRef, V newRef, boolean expectedMark, boolean newMark

)

AtomicStampedReference boolean compareAndSet (V expectedRef, V newRef, int expectedStamp, int newStamp

)

71 Accumulators

• DoubleAccumulator

• DoubleAdder

• LongAccumulator

• LongAdder

• (Striped64)

• void accumulate(long x)

• long get()

• long getThenReset()

• void reset()

72Non-blocking Guarantees

Wait-Freeбез ожидания

Per-thread progress is guaranteed

Lock-Freeбез блокировок

Overall progress is guaranteed

Obstruction-Freeбез препятствий

Per-thread progress is guaranteedif thread has been isolated (with all obstructing threads suspended)

73 AtomicLong-based Counter

public class CasCounter implements Counter {

private AtomicLong value = new AtomicLong();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}

}

Anyguarantees?A. Wait-FreeB. Lock-FreeC. Obstruction-FreeD. Noguarantees

74 AtomicLong-based Counter

public class CasCounter implements Counter {

private AtomicLong value = new AtomicLong();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}

}

Anyguarantees?A. Wait-FreeB. Lock-FreeC. Obstruction-FreeD. Noguarantees

75 AtomicLong-based Counter

public class CasCounter implements Counter {

private AtomicLong value = new AtomicLong();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}

}

Anyguaranteesonx64?A. Wait-FreeB. Lock-FreeC. Obstruction-FreeD. Noguarantees

76 AtomicLong-based Counter

public class CasCounter implements Counter {

private AtomicLong value = new AtomicLong();

public long get() {return value.get();

}

public void increment() {long v;do {

v = value.get();} while (value.compareAndSet(v, v + 1));

}

}

Anyguaranteesonx64?A. Wait-FreeB. Lock-FreeC. Obstruction-FreeD. Noguarantees

CAS в .NET

78Interlocked

79Interlocked

Неблокирующиеструктурыданных

81Неблокирующий

стек

82

Michael and Scott, 1996https://www.research.ibm.com/people/m/michael/podc-1996.pdf

Потоки помогают друг другу

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

Материалы

84Литература

85Материалы

• Все-все-все— bit.ly/concurrency-interest• Nitsan Wakart — psy-lob-saw.blogspot.com• АлексейШипилёв — shipilev.net• АндрейАкиньшин— aakinshin.net/ru/blog/

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