SlideShare una empresa de Scribd logo
1 de 68
Descargar para leer sin conexión
Что нового в j.u.c
(JSR 166e)
Дмитрий Чуйко
dmitry.chuyko@oracle.com
Outline
Введение
Что нового
Atomics
Locks
Accumulators
Collections
Slide 2/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
The following is intended to outline our general
product direction. It is intended for information
purposes only, and may not be incorporated into any
contract. It is not a commitment to deliver any
material, code, or functionality, and should not be
relied upon in making purchasing decisions. The
development, release, and timing of any features or
functionality described for Oracle’s products remains
at the sole discretion of Oracle.
Slide 3/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Введение
Slide 4/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Введение: Ситуация
Всем нужны масштабируемость, надёжность,
производительность
The Free Lunch Is Over, Herb Sutter, 2005
Многопоточность может возникать из-за
условий задачи
Многопроцессорность/многоядерность везде
Slide 5/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Цели
Параллелизация за кулисами
Загрузка процессора полезной работой
Хорошие алгоритмы
Slide 6/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Java Concurrency Timeline
JDK 1.0
  JMM
  synchronizied
  Thread
1996 1997 2004
JDK 1.2
  Collections
JDK 5
  JMM
  java.util.concurrent
JSRs
  JSR 133
  JSR 166
Doug Lea
 Concurrency
package
1998 2006
JDK 6
  Deques,
JSRs
  JSR 166x
2011
JDK 7
  ForkJoinPool,
JSRs
  JSR 166y
JDK 8
  java.util.concurrent
JSRs
  JSR 166e
Slide 7/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Состав
Java Concurrency Utilities
Executors
Synchronizers Collections
Atomics Locks Nano time
Slide 8/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Фундамент
Runtime
LockSupport
Unsafe
JVM
Intrinsics
OS
pthreads mutex
Hardware
CAS
Slide 9/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Атомарные переменные
@since 1.5
Обёртки примитивов, ссылок, управление
полями
– Compare-And-Set
– Атомарная арифметика
Slide 10/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Синхронизация
@since 1.5
Semaphores, mutexes, barriers, latches,
exchangers
– Удобство синхронизации
Locks
– Производительность
– Модель памяти. Эффект эквивалентен
synchronized
– Гибкость
Slide 11/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Concurrent Collections
@since 1.5
ArrayBlockingQueue, PriorityBlockingQueue,
LinkedBlockingQueue, SynchronousQueue,
DelayQueue
ConcurrentHashMap
CopyOnWriteArrayList
CopyOnWriteArraySet
Slide 12/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Concurrent Collections
@since 1.6, @since 1.7
LinkedBlockingDeque, LinkedTransferQueue
ConcurrentSkipListMap
ConcurrentSkipListSet
Slide 13/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
История: Task Scheduling
@since 1.5, @since 1.7
Executor’ы
– Выполнение асинхронных задач
– Политики выполнения
Slide 14/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Что нового
Slide 15/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Что нового: JC Utilities
Executors
ForkJoinPool (updated, CountedCompleter)
Collections Accumulators
ConcurrentHashMap (v8) LongAccumulator DoubleAccumulator
LongAdder DoubleAdder
LongAdderTable
Locks Atomics Synchronizers
StampedLock AtomicDoubleArray CompletableFuture
AtomicDouble
Slide 16/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics
Slide 17/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics: Чего не хватает
Для каких примитивных типов нет
Atomic-типов?
В каких числах чаще всего считаем?
Возникают массивы атомарных данных
Slide 18/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics: AtomicDouble
@since 1.8
Брат-близнец AtomicLong
Number, Serializable
compareAndSet(double expect, double update)
addAndGet(double delta)
Равенство битов значений
– doubleToRawLongBits()
Slide 19/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics: AtomicDoubleArray
@since 1.8
Брат-близнец AtomicLongArray
Serializable
compareAndSet(int i, double exp, double upd)
addAndGet(int i, double delta)
Равенство битов значений
– doubleToRawLongBits()
Slide 20/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics: Performance
Приводимые результаты
– Intel R○ Xeon R○ E5-2680 (2x8x2, 2.7 GHz)
– Linux x64 (RHEL 5.5, kernel 2.6.32)
– JDK 7 (1.7.0_11)
– OpenJDK JMH 1.0
Slide 21/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics: AtomicDoubleArray
Тест производительности
– Размер массива 2, 621, 440
– Читатели делают get()
– Писатели делают compareAndSet()
– Произвольный равномерный доступ
Slide 22/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Atomics: AtomicDoubleArray
0
200
400
25 50 75
% of writers
Readthroughput,ops/usec
Benchmark
AtomicDouble[]
AtomicDoubleArray
T=32
0
100
200
300
25 50 75 100
% of writers
Writethroughput,ops/usec
Benchmark
AtomicDouble[]
AtomicDoubleArray
T=32
Slide 23/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks
Slide 24/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: Чего бы хотелось
Блокировка на чтение, на запись
Чтение без блокировки
Upgrade/downgrade (RL↔WL)
Простота использования
И чтобы быстро работало
Slide 25/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: ReentrantReadWriteLock
@since 1.5
Lock, блокировка на чтение, на запись
Повторная входимость (reentrancy)
Пробная блокировка, таймауты,
прерываемость
Slide 26/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: ReentrantReadWriteLock
@since 1.5
Lock, блокировка на чтение, на запись
Повторная входимость (reentrancy)
Пробная блокировка, таймауты,
прерываемость
Conditions
Fair/unfair
Serializable. . .
Memory effects
Slide 26/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: ReentrantReadWriteLock
readLock() на чтение, writeLock() на
запись
Попробуйте написать оптимистичное чтение,
гарантировать memory effects
Downgrade WL→RL: захват RL под WL
Внутри работает с ThreadLocal
Slide 27/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
@since 1.8
Пример из javadoc
Slide 28/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Point
class Point {
private double x, y;
private final StampedLock sl = new StampedLock ();
...
Slide 29/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Optimistic Read
double distanceFromOrigin () { // A read -only method
long stamp = sl. tryOptimisticRead ();
double currentX = x;
double currentY = y;
if (!sl.validate(stamp )) {
stamp = sl.readLock ();
try {
currentX = x;
currentY = y;
} finally {
sl.unlockRead(stamp );
}
}
return Math.sqrt(currentX * currentX + currentY * currentY );
}
Slide 30/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Upgrade
void moveIfAtOrigin (double newX , double newY) { // upgrade
long stamp = sl.readLock (); // Could start with optimistic
try {
while (x == 0.0 && y == 0.0) {
long ws = sl. tryConvertToWriteLock (stamp );
if (ws != 0L) {
stamp = ws;
x = newX;
y = newY;
break;
}
else {
sl.unlockRead(stamp );
stamp = sl.writeLock ();
}
}
} finally {
sl.unlock(stamp );
}
}
Slide 31/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Оптимистичное чтение
Если проверки неудачные, можно захватить
блокировку
– Обычно удачные
Slide 32/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Оптимистичное чтение
Если проверки неудачные, можно захватить
блокировку
– Обычно удачные
Выигрыш
– Мало записей ⇒ в разы
– Нет записей ⇒ на порядки
– Вне блокировки проверенное состояние может
стать неактуальным
Slide 32/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Повышение уровня блокировки
– Может не быть выигрыша, если не
ограничивать запись
– Валидное состояние
Slide 33/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Locks: StampedLock
Повышение уровня блокировки
– Может не быть выигрыша, если не
ограничивать запись
– Валидное состояние
В штатном варианте может быть в разы
быстрее RRWL
– Не гарантировано!
– При этом потребляет меньше ресурсов
– Можно передавать метку
Slide 33/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators
Slide 34/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Задача
Инкрементируем счётчик в разных нитях
Нити подбирают работу и имеют доступ к
общему контексту
void call () { // N threads
...
invocations.increment ();
}
...
long getCount () {
return invocations .get ();
}
Что использовать для invocations?
Slide 35/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Простое решение
AtomicLong invocations = new AtomicLong (0L); // context
...
void call () { // N threads
...
invocations. getAndIncrement ();
}
...
long getCount () { // cumulative value
return invocations .get ();
}
Slide 36/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: AtomicLong
Sharing
Spin loop + CAS, много
Slide 37/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: LongAdder
Защита от коллизий за счёт структуры и
алгоритма
– PaddedAtomicLong[runtime.availableProcessors()]
Простой API
Number
Slide 38/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Решение
LongAdder invocations = new LongAdder (); // context
...
void call () { // N threads
...
invocations.increment ();
}
...
long getCount () { // cumulative value
return invocations .sum ();
}
Slide 39/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: DoubleAdder
Аналогичен LongAdder, только для double
Большая часть логики одинаковая
Slide 40/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Atomic Update
// AtomicLong , JDK 7
public final long addAndGet(long delta) {
for (;;) {
long current = get ();
long next = current + delta;
if ( compareAndSet (current , next ))
return next;
}
}
Хотим заменить ’+’ функцией
Slide 41/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Произвольные
коммутативные операции
LongAccumulator
LongAccumulator invocations =
new LongAccumulator (Long ::sum , 0L); // context
...
void call () { // N threads
...
invocations.accumulate (1);
}
...
long getCount () { // cumulative value
return invocations .get ();
}
DoubleAccumulator
Slide 42/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Atomics
AtomicXXX
– updateAndGet(current -> current + 1)
– getAndAccumulate(delta, (current, delta) -> current+delta)
Slide 43/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: LongMaxUpdater
LongAccumulator(Long::max, Long.MIN_VALUE)
Тест производительности
– accumulate(nextLocalLongMax)
Slide 44/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: LongMaxUpdater
10
100
1000
0 20 40 60
Threads
Throughput,ops/usec(logscale)
Benchmark Unshared CAS LongMaxUpdater AtomicLong long+Lock
Slide 45/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Accumulators: Подводные камни
Local, ThreadLocal – эффективнее, если
можно применить
get(), reset() под нагрузкой просаживают
производительность
– Обход всех ячеек
Границы эффекта
– Система до насыщения
– Итерации менее 1 мкс
Slide 46/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Collections
Slide 47/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: CHMv7
Lock striping
– Concurrency level
– Сегмент - ReentrantLock
get() без блокировки
Защита от алгоритмических атак
– Другой хэш для String
Slide 48/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: CHMv8
Lock striping
– Concurrency level не используется, подстройка
структуры в процессе работы
– Node (bucket): synchronized или StampedLock
Slide 49/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: CHMv8
Lock striping
– Concurrency level не используется, подстройка
структуры в процессе работы
– Node (bucket): synchronized или StampedLock
get() без блокировки или под блокировкой
на чтение
Slide 49/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: CHMv8
Lock striping
– Concurrency level не используется, подстройка
структуры в процессе работы
– Node (bucket): synchronized или StampedLock
get() без блокировки или под блокировкой
на чтение
Защита от алгоритмических атак
– Сбалансированное дерево для Comparable -
performance
Slide 49/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: v8 vs v7
Тест производительности
– put()
– Integer-like ключи
– Нормальное распределение
– 2, 621, 440 элементов
– concurrencyLevel == 32 (optimal)
Slide 50/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap:
Масштабируемость
1
10
0 20 40 60
Threads
Throughput,ops/usec(logscale)
Benchmark CHMv8 CHMv7 HashMap+ReentrantLock
Slide 51/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: Часть JDK 8
Часть методов появилась в других мапах
через default-реализации в Map
– putIfAbsent(), computeIfAbsent() атомарны в CHM
Slide 52/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: Часть JDK 8
Часть методов появилась в других мапах
через default-реализации в Map
– putIfAbsent(), computeIfAbsent() атомарны в CHM
Добавились новые методы и возможности
– map.merge(key, valueSuffix, String::concat)
– chm.values().parallelStream()
Slide 52/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
ConcurrentHashMap: Часть JDK 8
Часть методов появилась в других мапах
через default-реализации в Map
– putIfAbsent(), computeIfAbsent() атомарны в CHM
Добавились новые методы и возможности
– map.merge(key, valueSuffix, String::concat)
– chm.values().parallelStream()
Можно использовать лямбды и method
reference
– int2IntMap.computeIfAbsent(100, (k)->k/3)
– stream.map(theMap::get)
Slide 52/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
LongAdderTable: Задача
Регистрировать распределение объектов
– Моделирование
– Профилирование
void call () { // N threads
...
invocations.increment("call");
}
...
long getCount(String name) { // cumulative value
return invocations .sum(name );
}
Slide 53/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
LongAdderTable: Решение
Естественная комбинация
– new ConcurrentHashMap<K, LongAdder>()
Простой API
Serializable
Slide 54/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
LongAdderTable: API
install(K key)
increment(K key)
add(K key)
sum(K key)
и другие
Slide 55/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Заключение: Книги
Java Concurrency in Practice
Brian Goetz, Tim Peierls, Joshua Bloch, Joseph
Bowbeer, David Holmes, Doug Lea
Concurrent Programming in Java: Design
Principles and Patterns
Doug Lea
Slide 56/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Заключение: Ресурсы
Concurrency JSR-166 Interest Site
http://g.oswego.edu/dl/concurrency-interest/
JDK 8
http://jdk8.java.net/
Project Lambda
http://openjdk.java.net/projects/lambda/
JMH
http://openjdk.java.net/projects/code-tools/jmh/
Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Низкоуровневые API: Мотивация
JMM абстрактна, железо конкретно
Есть полезные трюки
Не используйте низкоуровневые API
напрямую
Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Низкоуровневые API: Unsafe
Не часть языка
– Обход JMM
– sun.misc
Unsafe API в Hotspot
– Аккуратный
– Абстрактный
– Достаточный
Не используйте Unsafe напрямую, это unsafe
Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Низкоуровневые API: Unsafe
Новая механика
– storeFence()
– loadFence()
– fullFence()
– Использование в реализации Locks
Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
Низкоуровневые API: StampedLock
Listing 1: Optimistic Read
/* volatile long state */
...
long stamp = sl. tryOptimisticRead (); /* s = state */
double currentX = x;
double currentY = y;
if (!sl.validate(stamp )) { /* unsafe.loadFence () */
...
stamp = sl.writeLock (); /* CAS(state , next) */
x = newX;
y = newY;
sl.unlock(stamp );
Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.

Más contenido relacionado

Similar a Talk juc jeeconf

Занимательные истории из жизни технической поддержки JVM
Занимательные истории из жизни технической поддержки JVMЗанимательные истории из жизни технической поддержки JVM
Занимательные истории из жизни технической поддержки JVMNikita Lipsky
 
Процесс изменения платформы Java
Процесс изменения платформы JavaПроцесс изменения платформы Java
Процесс изменения платформы JavaAlexey Fyodorov
 
Резервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условияхРезервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условияхSveta Smirnova
 
Полезное покрытие кода
Полезное покрытие кодаПолезное покрытие кода
Полезное покрытие кодаSQALab
 
Алексей Федоров
Алексей ФедоровАлексей Федоров
Алексей ФедоровCodeFest
 
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...Fwdays
 
Операционные системы 2015, лекция № 5
Операционные системы 2015, лекция № 5Операционные системы 2015, лекция № 5
Операционные системы 2015, лекция № 5Aleksey Bragin
 
Разбор сложных случаев OutOfMemoryError
Разбор сложных случаев OutOfMemoryErrorРазбор сложных случаев OutOfMemoryError
Разбор сложных случаев OutOfMemoryErrorVladimir Sitnikov
 
Новое поколение серверов SPARC
Новое поколение серверов SPARCНовое поколение серверов SPARC
Новое поколение серверов SPARCAndrey Akulov
 

Similar a Talk juc jeeconf (11)

Занимательные истории из жизни технической поддержки JVM
Занимательные истории из жизни технической поддержки JVMЗанимательные истории из жизни технической поддержки JVM
Занимательные истории из жизни технической поддержки JVM
 
Процесс изменения платформы Java
Процесс изменения платформы JavaПроцесс изменения платформы Java
Процесс изменения платформы Java
 
Резервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условияхРезервное копирование MySQL в экстремальных условиях
Резервное копирование MySQL в экстремальных условиях
 
Полезное покрытие кода
Полезное покрытие кодаПолезное покрытие кода
Полезное покрытие кода
 
Алексей Федоров
Алексей ФедоровАлексей Федоров
Алексей Федоров
 
Java in Motion
Java in MotionJava in Motion
Java in Motion
 
Philosophers
PhilosophersPhilosophers
Philosophers
 
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
Олег Миколайченко "Как перестать хранить секреты в git и начать использовать ...
 
Операционные системы 2015, лекция № 5
Операционные системы 2015, лекция № 5Операционные системы 2015, лекция № 5
Операционные системы 2015, лекция № 5
 
Разбор сложных случаев OutOfMemoryError
Разбор сложных случаев OutOfMemoryErrorРазбор сложных случаев OutOfMemoryError
Разбор сложных случаев OutOfMemoryError
 
Новое поколение серверов SPARC
Новое поколение серверов SPARCНовое поколение серверов SPARC
Новое поколение серверов SPARC
 

Talk juc jeeconf

  • 1. Что нового в j.u.c (JSR 166e) Дмитрий Чуйко dmitry.chuyko@oracle.com
  • 2. Outline Введение Что нового Atomics Locks Accumulators Collections Slide 2/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 3. The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. Slide 3/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 4. Введение Slide 4/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 5. Введение: Ситуация Всем нужны масштабируемость, надёжность, производительность The Free Lunch Is Over, Herb Sutter, 2005 Многопоточность может возникать из-за условий задачи Многопроцессорность/многоядерность везде Slide 5/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 6. История: Цели Параллелизация за кулисами Загрузка процессора полезной работой Хорошие алгоритмы Slide 6/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 7. История: Java Concurrency Timeline JDK 1.0   JMM   synchronizied   Thread 1996 1997 2004 JDK 1.2   Collections JDK 5   JMM   java.util.concurrent JSRs   JSR 133   JSR 166 Doug Lea  Concurrency package 1998 2006 JDK 6   Deques, JSRs   JSR 166x 2011 JDK 7   ForkJoinPool, JSRs   JSR 166y JDK 8   java.util.concurrent JSRs   JSR 166e Slide 7/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 8. История: Состав Java Concurrency Utilities Executors Synchronizers Collections Atomics Locks Nano time Slide 8/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 9. История: Фундамент Runtime LockSupport Unsafe JVM Intrinsics OS pthreads mutex Hardware CAS Slide 9/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 10. История: Атомарные переменные @since 1.5 Обёртки примитивов, ссылок, управление полями – Compare-And-Set – Атомарная арифметика Slide 10/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 11. История: Синхронизация @since 1.5 Semaphores, mutexes, barriers, latches, exchangers – Удобство синхронизации Locks – Производительность – Модель памяти. Эффект эквивалентен synchronized – Гибкость Slide 11/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 12. История: Concurrent Collections @since 1.5 ArrayBlockingQueue, PriorityBlockingQueue, LinkedBlockingQueue, SynchronousQueue, DelayQueue ConcurrentHashMap CopyOnWriteArrayList CopyOnWriteArraySet Slide 12/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 13. История: Concurrent Collections @since 1.6, @since 1.7 LinkedBlockingDeque, LinkedTransferQueue ConcurrentSkipListMap ConcurrentSkipListSet Slide 13/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 14. История: Task Scheduling @since 1.5, @since 1.7 Executor’ы – Выполнение асинхронных задач – Политики выполнения Slide 14/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 15. Что нового Slide 15/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 16. Что нового: JC Utilities Executors ForkJoinPool (updated, CountedCompleter) Collections Accumulators ConcurrentHashMap (v8) LongAccumulator DoubleAccumulator LongAdder DoubleAdder LongAdderTable Locks Atomics Synchronizers StampedLock AtomicDoubleArray CompletableFuture AtomicDouble Slide 16/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 17. Atomics Slide 17/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 18. Atomics: Чего не хватает Для каких примитивных типов нет Atomic-типов? В каких числах чаще всего считаем? Возникают массивы атомарных данных Slide 18/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 19. Atomics: AtomicDouble @since 1.8 Брат-близнец AtomicLong Number, Serializable compareAndSet(double expect, double update) addAndGet(double delta) Равенство битов значений – doubleToRawLongBits() Slide 19/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 20. Atomics: AtomicDoubleArray @since 1.8 Брат-близнец AtomicLongArray Serializable compareAndSet(int i, double exp, double upd) addAndGet(int i, double delta) Равенство битов значений – doubleToRawLongBits() Slide 20/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 21. Atomics: Performance Приводимые результаты – Intel R○ Xeon R○ E5-2680 (2x8x2, 2.7 GHz) – Linux x64 (RHEL 5.5, kernel 2.6.32) – JDK 7 (1.7.0_11) – OpenJDK JMH 1.0 Slide 21/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 22. Atomics: AtomicDoubleArray Тест производительности – Размер массива 2, 621, 440 – Читатели делают get() – Писатели делают compareAndSet() – Произвольный равномерный доступ Slide 22/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 23. Atomics: AtomicDoubleArray 0 200 400 25 50 75 % of writers Readthroughput,ops/usec Benchmark AtomicDouble[] AtomicDoubleArray T=32 0 100 200 300 25 50 75 100 % of writers Writethroughput,ops/usec Benchmark AtomicDouble[] AtomicDoubleArray T=32 Slide 23/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 24. Locks Slide 24/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 25. Locks: Чего бы хотелось Блокировка на чтение, на запись Чтение без блокировки Upgrade/downgrade (RL↔WL) Простота использования И чтобы быстро работало Slide 25/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 26. Locks: ReentrantReadWriteLock @since 1.5 Lock, блокировка на чтение, на запись Повторная входимость (reentrancy) Пробная блокировка, таймауты, прерываемость Slide 26/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 27. Locks: ReentrantReadWriteLock @since 1.5 Lock, блокировка на чтение, на запись Повторная входимость (reentrancy) Пробная блокировка, таймауты, прерываемость Conditions Fair/unfair Serializable. . . Memory effects Slide 26/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 28. Locks: ReentrantReadWriteLock readLock() на чтение, writeLock() на запись Попробуйте написать оптимистичное чтение, гарантировать memory effects Downgrade WL→RL: захват RL под WL Внутри работает с ThreadLocal Slide 27/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 29. Locks: StampedLock @since 1.8 Пример из javadoc Slide 28/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 30. Locks: StampedLock Point class Point { private double x, y; private final StampedLock sl = new StampedLock (); ... Slide 29/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 31. Locks: StampedLock Optimistic Read double distanceFromOrigin () { // A read -only method long stamp = sl. tryOptimisticRead (); double currentX = x; double currentY = y; if (!sl.validate(stamp )) { stamp = sl.readLock (); try { currentX = x; currentY = y; } finally { sl.unlockRead(stamp ); } } return Math.sqrt(currentX * currentX + currentY * currentY ); } Slide 30/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 32. Locks: StampedLock Upgrade void moveIfAtOrigin (double newX , double newY) { // upgrade long stamp = sl.readLock (); // Could start with optimistic try { while (x == 0.0 && y == 0.0) { long ws = sl. tryConvertToWriteLock (stamp ); if (ws != 0L) { stamp = ws; x = newX; y = newY; break; } else { sl.unlockRead(stamp ); stamp = sl.writeLock (); } } } finally { sl.unlock(stamp ); } } Slide 31/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 33. Locks: StampedLock Оптимистичное чтение Если проверки неудачные, можно захватить блокировку – Обычно удачные Slide 32/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 34. Locks: StampedLock Оптимистичное чтение Если проверки неудачные, можно захватить блокировку – Обычно удачные Выигрыш – Мало записей ⇒ в разы – Нет записей ⇒ на порядки – Вне блокировки проверенное состояние может стать неактуальным Slide 32/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 35. Locks: StampedLock Повышение уровня блокировки – Может не быть выигрыша, если не ограничивать запись – Валидное состояние Slide 33/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 36. Locks: StampedLock Повышение уровня блокировки – Может не быть выигрыша, если не ограничивать запись – Валидное состояние В штатном варианте может быть в разы быстрее RRWL – Не гарантировано! – При этом потребляет меньше ресурсов – Можно передавать метку Slide 33/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 37. Accumulators Slide 34/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 38. Accumulators: Задача Инкрементируем счётчик в разных нитях Нити подбирают работу и имеют доступ к общему контексту void call () { // N threads ... invocations.increment (); } ... long getCount () { return invocations .get (); } Что использовать для invocations? Slide 35/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 39. Accumulators: Простое решение AtomicLong invocations = new AtomicLong (0L); // context ... void call () { // N threads ... invocations. getAndIncrement (); } ... long getCount () { // cumulative value return invocations .get (); } Slide 36/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 40. Accumulators: AtomicLong Sharing Spin loop + CAS, много Slide 37/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 41. Accumulators: LongAdder Защита от коллизий за счёт структуры и алгоритма – PaddedAtomicLong[runtime.availableProcessors()] Простой API Number Slide 38/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 42. Accumulators: Решение LongAdder invocations = new LongAdder (); // context ... void call () { // N threads ... invocations.increment (); } ... long getCount () { // cumulative value return invocations .sum (); } Slide 39/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 43. Accumulators: DoubleAdder Аналогичен LongAdder, только для double Большая часть логики одинаковая Slide 40/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 44. Accumulators: Atomic Update // AtomicLong , JDK 7 public final long addAndGet(long delta) { for (;;) { long current = get (); long next = current + delta; if ( compareAndSet (current , next )) return next; } } Хотим заменить ’+’ функцией Slide 41/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 45. Accumulators: Произвольные коммутативные операции LongAccumulator LongAccumulator invocations = new LongAccumulator (Long ::sum , 0L); // context ... void call () { // N threads ... invocations.accumulate (1); } ... long getCount () { // cumulative value return invocations .get (); } DoubleAccumulator Slide 42/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 46. Accumulators: Atomics AtomicXXX – updateAndGet(current -> current + 1) – getAndAccumulate(delta, (current, delta) -> current+delta) Slide 43/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 47. Accumulators: LongMaxUpdater LongAccumulator(Long::max, Long.MIN_VALUE) Тест производительности – accumulate(nextLocalLongMax) Slide 44/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 48. Accumulators: LongMaxUpdater 10 100 1000 0 20 40 60 Threads Throughput,ops/usec(logscale) Benchmark Unshared CAS LongMaxUpdater AtomicLong long+Lock Slide 45/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 49. Accumulators: Подводные камни Local, ThreadLocal – эффективнее, если можно применить get(), reset() под нагрузкой просаживают производительность – Обход всех ячеек Границы эффекта – Система до насыщения – Итерации менее 1 мкс Slide 46/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 50. Collections Slide 47/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 51. ConcurrentHashMap: CHMv7 Lock striping – Concurrency level – Сегмент - ReentrantLock get() без блокировки Защита от алгоритмических атак – Другой хэш для String Slide 48/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 52. ConcurrentHashMap: CHMv8 Lock striping – Concurrency level не используется, подстройка структуры в процессе работы – Node (bucket): synchronized или StampedLock Slide 49/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 53. ConcurrentHashMap: CHMv8 Lock striping – Concurrency level не используется, подстройка структуры в процессе работы – Node (bucket): synchronized или StampedLock get() без блокировки или под блокировкой на чтение Slide 49/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 54. ConcurrentHashMap: CHMv8 Lock striping – Concurrency level не используется, подстройка структуры в процессе работы – Node (bucket): synchronized или StampedLock get() без блокировки или под блокировкой на чтение Защита от алгоритмических атак – Сбалансированное дерево для Comparable - performance Slide 49/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 55. ConcurrentHashMap: v8 vs v7 Тест производительности – put() – Integer-like ключи – Нормальное распределение – 2, 621, 440 элементов – concurrencyLevel == 32 (optimal) Slide 50/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 56. ConcurrentHashMap: Масштабируемость 1 10 0 20 40 60 Threads Throughput,ops/usec(logscale) Benchmark CHMv8 CHMv7 HashMap+ReentrantLock Slide 51/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 57. ConcurrentHashMap: Часть JDK 8 Часть методов появилась в других мапах через default-реализации в Map – putIfAbsent(), computeIfAbsent() атомарны в CHM Slide 52/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 58. ConcurrentHashMap: Часть JDK 8 Часть методов появилась в других мапах через default-реализации в Map – putIfAbsent(), computeIfAbsent() атомарны в CHM Добавились новые методы и возможности – map.merge(key, valueSuffix, String::concat) – chm.values().parallelStream() Slide 52/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 59. ConcurrentHashMap: Часть JDK 8 Часть методов появилась в других мапах через default-реализации в Map – putIfAbsent(), computeIfAbsent() атомарны в CHM Добавились новые методы и возможности – map.merge(key, valueSuffix, String::concat) – chm.values().parallelStream() Можно использовать лямбды и method reference – int2IntMap.computeIfAbsent(100, (k)->k/3) – stream.map(theMap::get) Slide 52/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 60. LongAdderTable: Задача Регистрировать распределение объектов – Моделирование – Профилирование void call () { // N threads ... invocations.increment("call"); } ... long getCount(String name) { // cumulative value return invocations .sum(name ); } Slide 53/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 61. LongAdderTable: Решение Естественная комбинация – new ConcurrentHashMap<K, LongAdder>() Простой API Serializable Slide 54/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 62. LongAdderTable: API install(K key) increment(K key) add(K key) sum(K key) и другие Slide 55/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 63. Заключение: Книги Java Concurrency in Practice Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, Doug Lea Concurrent Programming in Java: Design Principles and Patterns Doug Lea Slide 56/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 64. Заключение: Ресурсы Concurrency JSR-166 Interest Site http://g.oswego.edu/dl/concurrency-interest/ JDK 8 http://jdk8.java.net/ Project Lambda http://openjdk.java.net/projects/lambda/ JMH http://openjdk.java.net/projects/code-tools/jmh/ Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 65. Низкоуровневые API: Мотивация JMM абстрактна, железо конкретно Есть полезные трюки Не используйте низкоуровневые API напрямую Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 66. Низкоуровневые API: Unsafe Не часть языка – Обход JMM – sun.misc Unsafe API в Hotspot – Аккуратный – Абстрактный – Достаточный Не используйте Unsafe напрямую, это unsafe Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 67. Низкоуровневые API: Unsafe Новая механика – storeFence() – loadFence() – fullFence() – Использование в реализации Locks Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.
  • 68. Низкоуровневые API: StampedLock Listing 1: Optimistic Read /* volatile long state */ ... long stamp = sl. tryOptimisticRead (); /* s = state */ double currentX = x; double currentY = y; if (!sl.validate(stamp )) { /* unsafe.loadFence () */ ... stamp = sl.writeLock (); /* CAS(state , next) */ x = newX; y = newY; sl.unlock(stamp ); Slide 57/57. Copyright c○ 2013, Oracle and/or its affiliates. All rights reserved.