Многопоточность в Java.ppt
- Количество слайдов: 39
Многопоточность в Java
Введение • Hardware • Software • Операционная система – Работа прикладного ПО – Один процессор, много программ – Многозадачность, планировщик – Программа и процесс 2
Процессы и потоки • Процесс • Поток, отличие от процесса Поток 1. 1 Поток 1. 2 Процесс 1 Поток 1. 3 Поток 2. 1 Поток 2. 2 Процесс 2 • Не путать с потоками данных (streams) 3
Многопоточность • Параллельное выполнение потоков • Переключение контекста 4
Практическое применение • Увеличение производительности • Параллельные алгоритмы – Альфа-бета отсечения – Сортировка слиянием • UI + вычисления – Компьютерная игра – Spell checker 5
Практическое применение • Упрощение программы (несколько различных логических функций, асинхронные действия) – Чтение + обработка – Текстовый редактор (асинхронные бэкапы) • Повторение последовательных алгоритмов – Веб-сервер (обслуживание мн-ва клиентов) – Обработка множества фотографий 6
Проблемы и трудности • Атомарные и неатомарные операции – Long, Double • Общие ресурсы – Одновременный доступ к общим данным (порча данных) • Состояние гонки – Зависимость порядка выполнения • Сложность отладки 7
Неатомарные операции • long и double – неатомарные типы • Только часть переменной м. б. обновлена за одну атомарную операцию • Между обновлениями могут «вклиниться» другие потоки и прочитать «недообновлённую» переменную 8
Общие ресурсы • Пример: «общий» связанный список • Первый поток обходит список, второй поток удаляет элемент • Может возникнуть ситуация, когда элемент удалён одним потоком, а второй поток пытается получить к нему доступ 9
Состояние гонки • Ситуация, когда порядок выполнения одного потока зависит от другого 1. if в потоке 2 проверяет x на чётность. 2. Оператор «x++» в потоке 1 увеличивает x на единицу. 3. Оператор вывода в потоке 2 выводит « 1» , хотя, казалось бы, переменная проверена на чётность. // Общая переменная int x = 0; // Поток 1: while (!stop) { x++; } // Поток 2: while (!stop) { if (x%2 == 0) System. out. println(x); } 10
Решение проблем • Использование правильных типов данных (Atomic. Long) или volatile • Синхронизация – Мьютексы, критические секции и т. д. – События (wait, notify, sleep) • Рассмотрим на примерах 11
Классические задачи • Основные – Одновременный доступ к ресурсу – Производитель-потребитель • И другие – Не будут рассмотрены в рамках презентации 12
Потоки в Java • Класс Thread – поток – Позволяет создавать потоки и производить операции с ними • Интерфейс Runnable – сущность, которая может быть запущена – public void run(); • Thread реализует Runnable 13
Создание потока • main() – главный поток • Простейший способ – анонимный класс // Создание потока Thread t = new Thread(new Runnable() { public void run() { System. out. println("Hello"); } }); // Запуск потока t. start(); 14
Создание потока • Ещё один способ – Класс, реализующий Runnable – Реализовать метод run() public class my. Task implements Runnable { public void run() { // действия } } // Создание потока Thread t = new Thread(new my. Task()); // Запуск потока t. start(); 15
Создание потока • Ещё один способ – Класс, наследующийся от Thread – Реализовать метод run() public class my. Task extends Thread { public void run() { // действия } } // Создание потока Thread t = new my. Task(); // Запуск потока t. start(); • Можно вызвать start() в конструкторе 16
Одновременный доступ • • Атомарные типы данных и volatile Мьютекс (lock, unlock) Критическая секция (synhronized) Синхронизированный метод 17
Специальные атомарные типы • Atomic. Integer, Atomic. Boolean, Atomic. Long, Atomic. Integer. Array • Синхронизированы не только чтение и запись, но и операции, обычно не являющиеся атомарными (инкремент, декремент) 18
Ключевое слово volatile • Не сохраняются «внутрипоточные» копии • Синхронизация чтения и записи переменной volatile • Не синхронизируются неатомарные операции my. Volatile. Var++; аналогично: int temp = 0; synchronize(my. Volatile. Var) { temp = my. Volatile. Var; } temp++; synchronize(my. Volatile. Var) { my. Volatile. Var = temp; } 19
Мьютекс • • Самый низкий уровень абстракции «Ручное» управление Плюсы: гибкость Минусы: неосторожность использования ведёт к трудностям и ошибкам 20
Пример мьютекса import java. util. concurrent. locks. *; Lock locker = new Reentrant. Lock(); locker. lock(); try { // действия } finally { locker. unlock(); } 21
Критическая секция • «Синхронизированный» блок кода • Любой объект может служить объектом синхронизации • Снятие блокировки производится автоматически 22
Пример критической секции synchronized (object) { // действия 1 } // … synchronized (object) { // действия 2 } 23
Синхронизированные методы • Каждый синхронизированный метод текущего класса – критическая секция • Объектом синхронизации выступает объект текущего класса • Если один поток выполняет какой-либо синхронизированный метод, остальные потоки его ждут 24
Пример синхронизации методов public class my. Class { public void a() { … } synchronized public void b() { … } synchronized public void c() { … } } 25
Производитель-потребитель • Один поток производит данные, второй их потребляет • Несколько потоков производят данные и несколько их потребляют • Данные могут храниться в очереди 26
Производитель-потребитель (1) • Класс данных class Data { private Object data; public void set(Object data) { … } public Object get() { … } } 27
Производитель-потребитель (2) • Установка значения public void set(Object d) { while (true) { synchronized (this) { if (this. data == null) { this. data = d; break; } } } 28
Производитель-потребитель (3) • Получение значения public Object get() { while (true) { synchronized (this) { if (data != null) { Object d = data; data = null; return d; } } } 29
Производитель-потребитель • Данная модель неэффективна – Бесконечные циклы впустую тратят процессорное время • Использование sleep(time) не помогает – Маленькое время ожидания тратит процессорное время – Если «спать» долго, можно «проспать» – sleep() не снимает блокировку 30
Использование монитора • Любой объект может быть монитором • Для взаимодействия с монитором поток должен иметь блокировку на него • Методы монитора – wait(time? ) – ожидание монитора – notify() – извещение одного из ждущих потоков – notify. All() – извещение всех ждущих потоков 31
Производитель-потребитель (2) • Установка значения public synchronized void set(Object data) throws Interrupted. Exception { while (data != null) wait(); this. data = data; notify(); } 32
Производитель-потребитель (3) • Получение значения public synchronized Object get() throws Interrupted. Exception { while (data == null) wait(); Object d = data; data = null; notify(); return d; } 33
Ожидание окончания потока • Методы класса Thread – join() – ожидать до завершения – join(long millis) – ожидать до завершения или истечения millis миллисекунд – join(long millis, long nanos) – ожидать до завершения или истечения millis миллисекунд и nanos миллисекунд 34
Прерывание потока • Методы класса Thread – interrupt() – установить флаг прерывания – is. Interrupted() – проверить флаг прерывания – interrupted() – проверить и сбросить флаг прерывания 35
Дополнительные методы • Приостановка выполнения – sleep(time) – приостановить поток на время – yield() – позволить выполниться другим потокам • Получение текущего потока – current. Thread() • Завершение потока – destroy() 36
Новый класс ошибок • Deadlock (взаимная блокировка) • Пессимизация скорости из-за неправильного применения синхронизации – Одновременный просмотр списка 37
java. util. concurrent • Потоко-безопасные структуры данных 38
Спасибо за внимание! 39


