10. 10
Новичкам в области
многопоточности
Sorry
Перейдите в другой зал
Новичкам в неблокирующей
синхронизации
Короткое введение
Продвинутым многопоточным
программистам
Поговорим о деталях
реализации CAS/atomics!
Хипстерам Поговорим про хайп!
Immutable vs. Mutable
14. 14
Параллелизм — ОС
• Слушать музыку и переписываться в фейсбуке
в Одноклассниках
• При зависании одной программы другие
продолжают работать
• и т.п.
15. 15
Преимущества параллелизма
• Использование нескольких ядер/процессоров
- Да и на 1 ядре тоже! (async I/O)
• Простота моделирования
- Абстракция: фреймворк забирает сложность
• Упрощенная обработка асинхронных событий
• Более отзывчивые интерфейсы пользователя
- Event Dispatch Thread (EDT), async calls
16. 16
Параллелизм на уровне отдельно взятой программы
• Эффективное использование ресурсов
• Удобство, простота написания кода
• Справедливость
- Обработка запросов пользователей на серверах
соцсети с одинаковым приоритетом
- Читатели и писатели
- Fairness (честность)
22. 22
Simple Counter
public class SimpleCounter implements Counter {
long value = 0;
public long get() {
return value;
}
public void increment() {
value++;
}
}
23. 23
Volatile Counter
public class VolatileCounter implements Counter {
volatile long value = 0;
public long get() {
return value;
}
public void increment() {
value++;
}
}
24. 24
Synchronized Counter
public class SynchronizedCounter implements Counter {
long value = 0;
public synchronized long get() {
return value;
}
public synchronized void increment() {
value++;
}
}
37. 37
CAS Semantics
public 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. 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. 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));
}
}
41. 41
CAS in Java
Since Java 5, JSR166
java.util.concurrent.atomic
• Scalars
• Field updaters
• Arrays
• Compound variables
• Accumulators/Adders
since Java 8
44. 44
• boolean compareAndSet(long expect, long update)
• long addAndGet(long delta)
• long getAndAdd(long delta)
• long getAndDecrement()
• long getAndIncrement()
• long incrementAndGet()
• …
AtomicLong
45. 45
• boolean compareAndSet(long expect, long update)
• long addAndGet(long delta)
• long getAndAdd(long delta)
• long getAndDecrement()
• long getAndIncrement()
• long incrementAndGet()
• …
AtomicLong
46. 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. 47
Недостатки CAS
Contended CAS —> tons of useless CPU cycles
do {
v = value.get();
} while (value.compareAndSet(v, v + 1));
Написание быстрых и корректных алгоритмов на CAS
требует экспертизы
48. 48
AtomicLong
• boolean compareAndSet(long expect, long update)
• long addAndGet(long delta)
• long getAndAdd(long delta)
• long getAndDecrement()
• long getAndIncrement()
• long incrementAndGet()
• …
49. 49
Get-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);
}
}
62. 62
Field Updaters
• AtomicIntegerFieldUpdater
– Reflection-based updater for volatile int
• AtomicLongFieldUpdater
– Reflection-based updater for volatile long
• AtomicReferenceFieldUpdater
– Reflection-based updater for volatile object
70. 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
)
72. 72
Non-blocking Guarantees
Wait-Free
без ожидания
Per-thread progress is guaranteed
Lock-Free
без блокировок
Overall progress is guaranteed
Obstruction-Free
без препятствий
Per-thread progress is guaranteed
if thread has been isolated
(with all obstructing threads suspended)
73. 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));
}
}
Any guarantees?
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
D. No guarantees
74. 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));
}
}
Any guarantees?
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
D. No guarantees
75. 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));
}
}
Any guarantees on x64?
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
D. No guarantees
76. 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));
}
}
Any guarantees on x64?
A. Wait-Free
B. Lock-Free
C. Obstruction-Free
D. No guarantees