Upload
codefest
View
758
Download
0
Embed Size (px)
Citation preview
8
Новичкам в области многопоточности
SorryПерейдите в другой зал
Новичкам в неблокирующей синхронизации
Короткое введение
9
Новичкам в области многопоточности
SorryПерейдите в другой зал
Новичкам в неблокирующей синхронизации
Короткое введение
Продвинутым многопоточным программистам
Поговорим о деталях реализации CAS/atomics!
10
Новичкам в области многопоточности
SorryПерейдите в другой зал
Новичкам в неблокирующей синхронизации
Короткое введение
Продвинутым многопоточным программистам
Поговорим о деталях реализации CAS/atomics!
Хипстерам Поговорим про хайп!Immutable vs. Mutable
11Модели
• Модельсразделяемойпамятью- Операциинаатомарныхрегистрах:read,write- Удобнопрограммировать,всепривыкли
• Модельспередачейсообщений- Операции:send,onReceive- Похожанато,какреальноработаетжелезо
14Параллелизм — ОС
• СлушатьмузыкуипереписыватьсявфейсбукевОдноклассниках
• Призависанииоднойпрограммыдругиепродолжаютработать
• ит.п.
15Преимущества параллелизма
• Использованиенескольких ядер/процессоров- Даина1ядретоже!(async I/O)
• Простота моделирования- Абстракция:фреймворк забираетсложность
• Упрощеннаяобработкаасинхронных событий• Болееотзывчивые интерфейсыпользователя- EventDispatchThread(EDT),async calls
16Параллелизм на уровне отдельно взятой программы
• Эффективное использованиересурсов• Удобство,простота написаниякода• Справедливость- Обработказапросовпользователейнасерверахсоцсети содинаковымприоритетом
- Читателииписатели
- Fairness(честность)
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.*
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++;
}
}
27 Проблемы блокировок
• Взаимоблокировки (Deadlocks)
• Инверсия приоритетов
• Надежность — вдруг владелец блокировки помрет?
28 Проблемы блокировок
• Взаимоблокировки (Deadlocks)
• Инверсия приоритетов
• Надежность — вдруг владелец блокировки помрет?
• Performance– Параллелизма в критической секции нет!– Владелец блокировки может быть вытеснен планировщиком
29ЗаконАмдала
α часть общего объема вычислений, которую нельзя распараллелить
1-α часть, которую можно распараллелить
p количество потоков
30ЗаконАмдала
Sp=𝟏
α#𝟏%α𝐩
α часть общего объема вычислений, которую нельзя распараллелить
1-α часть, которую можно распараллелить
p количество потоков
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));
}}
41CAS in Java
Since Java 5, JSR166
java.util.concurrent.atomic
• Scalars• Field updaters• Arrays• Compound variables• Accumulators/Adders
since Java 8
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);
}
}
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
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)
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);
}
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
82
Michael and Scott, 1996https://www.research.ibm.com/people/m/michael/podc-1996.pdf
Потоки помогают друг другу
Неблокирующаяочередь
85Материалы
• Все-все-все— bit.ly/concurrency-interest• Nitsan Wakart — psy-lob-saw.blogspot.com• АлексейШипилёв — shipilev.net• АндрейАкиньшин— aakinshin.net/ru/blog/