Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor

260 vues

Publié le

Курс "Программирование на Java". Лекция 06 "Многопоточность".

Процессы, потоки. Старт и остановка потока. Организация работы с памятью - synchronized, volatile, Atomic*. Immutable design. Проблемы многопоточности - deadlock, livelock, starvation. Примитивы синхронизации - ReentrantLock, ReadWriteLock, CountDownLatch. Concurrent-коллекции.

МФТИ, 2016 год. Лектор - Лаврентьев Федор Сергеевич

Publié dans : Logiciels
  • Soyez le premier à commenter

Programming Java - Lection 06 - Multithreading - Lavrentyev Fedor

  1. 1. 6. Многопоточность Программирование на Java Федор Лаврентьев МФТИ, 2016
  2. 2. Потоки
  3. 3. Процесс и поток • Процесс • Выделенная память • Процессорное время расходуется потоками • Порождается через fork • Общается с другими процессами через сокеты и shared memory • Поток • Общая память процесса • Собственный кеш • Расходует процессорное время • Порождается внутри процесса • Общается с другими потоками через общую память процесса
  4. 4. java.lang.Thread • start(), run() • static sleep(), static yield() • stop(), destroy() • interrupt(), isInterrupted(), static interrupted() • setDaemon(), isDaemon() • join() • getState(): • NEW • RUNNABLE • BLOCKED • WAITING, TIMED_WAITING • TERMINATED
  5. 5. Старт потока через override public void runOverridenThread() { Thread thread = new Thread() { @Override public void run() { // do something } }; thread.start(); }
  6. 6. Старт потока с Runnable public void runRunnableInThread() { Thread thread = new Thread(new Runnable() { @Override public void run() { // do something } }); thread.start(); }
  7. 7. Прерывание потока public void interruptThread() throws Exception { Thread thread = new Thread(new Runnable() { @Override public void run() { while (!Thread.interrupted()) { // Do something useful } // Thread interrupted } }); thread.start(); Thread.sleep(1); thread.interrupt(); }
  8. 8. Прерывание блокирующего вызова public void interruptThread() throws Exception { Thread thread = new Thread(new Runnable() { @Override public void run() { while (!Thread.interrupted()) { // Do something useful try { Thread.sleep(1000); // blocking call } catch (InterruptedException e) { // Thread interrupted } } // Thread interrupted } }); thread.start(); Thread.sleep(1); thread.interrupt(); }
  9. 9. Работа с памятью
  10. 10. synchronized • Критическая секция • Допускается повторное вхождение (reentrant) • Синхронизироваться можно по любому объекту • Необходимо минимизировать размер критических секций • По возможности, дробить критические секции на части • Можно использовать альтернативные блокировки
  11. 11. synchronized public static synchronized void sMethod() { // тело метода } public static void sMethodDescribed () { synchronized (SynchronizedExample.class) { // тело метода } } public synchronized void iMethod() { // тело метода } public void iMethodDescribed() { synchronized (this) { // тело метода } } private final Object lock = new Object(); public void anotherObject () { synchronized (lock) { // тело метода } }
  12. 12. volatile • Форсирует работу с памятью в обход кешей • Гарантирует атомарное чтение и запись для double и long • Не гарантирует атомарный инкремент private volatile long value;
  13. 13. Atomic* • Базируются на операции compareAndSet(previous, next) • Это отдельная инструкция байт-кода JVM • Гарантирует атомарность чтения, записи и инкремента • java.util.concurrent.atomic.*: • AtomicInteger • AtomicLong • AtomicBoolean • AtomicReference<T> • AtomicIntegerArray • AtomicLongArray
  14. 14. Atomic incrementAndGet() public class AtomicInteger extends Number { private volatile int value; private native boolean compareAndSet(int current, int next); public final int incrementAndGet () { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) { return next; } } } }
  15. 15. Atomic getAndIncrement() public class AtomicInteger extends Number { private volatile int value; private native boolean compareAndSet(int current, int next); public final int getAndIncrement() { for (;;) { int current = get(); int next = current + 1; if (compareAndSet(current, next)) { return current; } } } }
  16. 16. Immutable • Неизменяемые объекты не нуждаются в синхронизации состояния, а значит, потокобезопасны • Все поля – final (либо не изменяются) • Все mutable параметры конструктора скопированы • Ссылки на внутренние mutable объекты не публикуются • Родительский класс также immutable • Нет утечки ссылки на this из конструктора
  17. 17. Проблемы многопоточности
  18. 18. Deadlock class Account { public int money; } class AccountManager { public void transfer(Account from, Account to, int amount) { assert amount > 0; synchronized (from) { assert from.money >= amount; synchronized (to) { to.money += amount; from.money -= amount; } } } }
  19. 19. Lock ordering class Account { public int money; public final long id; } class AccountManager { public void transfer(Account from, Account to, int amount) { assert amount > 0; assert from.number != to.number; Object first = from.number < to.number ? from : to; Object second = from.number < to.number ? to : from; synchronized (first) { synchronized (second) { to.money += amount; from.money -= amount; } } } }
  20. 20. Livelock • Поток успешно получает блокировку, однако выполнить полезное действие не может • Два потока конфликтуют, откатывают результаты своей работы и пытаются через фиксированное время повторить попытку (например, делают sleep(1000)). • При следующей попытке они опять будут конфликтовать • Пример – задача про обедающих философов • Решение – случайная задержка
  21. 21. Starvation • Бесконечные циклы – холостая утилизация CPU • sleep при взятой блокировке • Blocking IO при взятой блокировке • Неоптимальные приоритеты потоков в ОС
  22. 22. Решение проблем • Не использовать многопоточность • Не разделять состояние между потоками • Разделять только immutable-состояние • Использовать lock-free алгоритмы • Использовать готовые примитивы синхронизации • Аккуратнее программировать синхронизацию
  23. 23. Примитивы синхронизации https://habrahabr.ru/company/luxoft/blog/157273/
  24. 24. Lock (ReentrantLock) • lock() • unlock() • tryLock() • tryLock(long timeout)
  25. 25. ReadWriteLock • readLock().lock() • readLock().unlock() • writeLock().lock() • writeLock().unlock() http://www.java67.com/2012/08/5-thread-interview-questions-answers-in.html
  26. 26. CountDownLatch • new CountDownLatch(int count) • await() • countDown() http://www.topjavatutorial.com/java/countdownlatch-in-java/
  27. 27. А также • Semaphore • CyclicBarrier • Exchanger • Phaser
  28. 28. Concurrent-коллекции • Vector, Stack, Hashtable • Collections.synchronized*() • ConcurrentHashMap, ConcurrentSkipListMap • CopyOnWriteArrayList, CopyOnWriteArraySet • BlockingQueue – ArrayBQ, LinkedBQ • ConcurrentLinkedQueue

×