
09-Threads,Concurrency.pptx
- Количество слайдов: 26
Лекция 9. Многопоточность в Java. Синхронизация. Пакеты библиотек java. util. concurrent Лекции по Java SE Александр Харичкин, Performance Support Manager, Net. Cracker © 2013 Net. Cracker Technology Corporation Confidential
План лекции • Многозадачность (multithreading) и Java API • • • Поддержка многозадачности в Java Способы создания потока Управление потоком Потоки-демоны Приоритеты потоков • Одновременный доступ (concurrency) и синхронизация • Java Concurrency API © 2013 Net. Cracker Technology Corporation Confidential 2
Многозадачность (многопоточность) Что такое многозадачность? • Поток – часть приложения, исполняющая определенную задачу • Многозадачность – возможность исполнять несколько независимых задач одновременно • Потоки разделяют все системные ресурсы, при этом память разделяют только взаимодействующие потоки • ОС управляет исполнением потоков и их доступом к общим ресурсам Зачем нужна многозадачность? • Серверные приложения (параллельная обработка нескольких запросов) • Графические приложения • Обработка большого объема данных • Другие фоновые операции © 2013 Net. Cracker Technology Corporation Confidential 3
Многозадачность в Java • Java поддерживает многозадачность и предоставляет интерфейс управления потоками (каждый поток представляется экземпляром класса java. lang. Thread) • Java предоставляет интерфейс взаимодействия между потоками • Java поддерживает синхронизацию доступа к данным • К примеру, Garbage Collector работает в отдельном потоке. © 2013 Net. Cracker Technology Corporation Confidential 4
Создание потока исполнения – способ № 1 Способ № 1: наследование от класса java. lang. Thread //Объявление public class My. Thread extends Thread { public void run (){//Переопределение метода //Действия, выполняемые потоком } } //Запуск public class Thread. Test 1 { public static void main (String args[]){ Thread thread = new My. Thread (); thread. start (); // Здесь будет вызван метод run() } } Достоинство – минимум кода. Недостатки: 1) Нельзя наследоваться от другого класса 2) Неверный смысл: идеологическая связь с наследованием © 2013 Net. Cracker Technology Corporation Confidential 5
Создание потока исполнения – способ № 2 Способ № 2: реализация интерфейса java. lang. Runnable //Объявление public class My. Runnable implements Runnable { public void run (){//Реализация метода //Действия, выполняемые потоком } } //Запуск public class Thread. Test 2 { public static void main (String args[]){ Runnable run = new My. Runnable (); Thread thread = new Thread (run); thread. start (); // Здесь будет вызван метод run() } } © 2013 Net. Cracker Technology Corporation Confidential 6
Управление исполнением потока public static void sleep(long millis) throws Interrupted. Exception приостанавливает текущий поток как минимум на millis миллисекунд public static void yield() приостанавливает текущий поток, предоставляя возможность выполнять другие потоки (обычно необходимо в циклах, если там не вызывается sleep) public final void join() throws Interrupted. Exception вводит текущий поток в ожидание завершения другого потока public final boolean is. Alive() получает состояние потока (true – если поток запущен и выполняется, false – если поток не был запущен или завершился) public final void stop() насильственно останавливает поток, неконтролируемо освобождая все ресурсы public final void suspend() приостанавливает выполнение до вызова метода resume(); зачастую приводит к deadlock public final void resume() возобновляет выполнение потока, приостановленного методом suspend() ec pr e d © 2013 Net. Cracker Technology Corporation Confidential 7
Управление исполнением потока: прерывание Правильное прерывание потоков: public void interrupt() пытается выставить статус потока в “прерванный”, иначе (если поток находится в ожидании) очищает статус и порождает Interrupted. Exception в потоке public boolean is. Interrupted() - проверяет статус потока public static boolean interrupted() проверяет статус текущего потока, при этом очищая его • Используя interrupt(), нельзя остановить поток без его “согласия” • Чтобы поток можно было корректно остановить, вместо while (condition){. . } нужно писать while (condition && !Thread. current. Thread(). is. Interrupted()) {. . } + при вызове методов sleep, join нужно в catch(Interrupted. Exception) завершать run() © 2013 Net. Cracker Technology Corporation Confidential 8
Потоки-демоны • Демон – это поток, который может существовать неограниченное время. • Если в программе остаются только потоки-демоны, то такая программа завершает работу. В противном случае она ожидает завершения всех потоков, не являющихся демонами. • Назначение демонов – обслуживание других потоков • Например, таймер • API • задание типа потока (true – демон, false – иначе): public final void set. Daemon(boolean on) • получение типа потока: public final boolean is. Daemon() © 2013 Net. Cracker Technology Corporation Confidential 9
Приоритеты потоков • Задание приоритета потока public final void set. Priority(int new. Priority); • Приоритет изменяется от Thread. MIN_PRIORITY (1) до Thread. MAX_PRIORITY (10) включительно. • Нормальный приоритет (default): Thread. NORM_PRIORITY (5). • Получение приоритета потока public final int get. Priority(); • Количество уровней приоритетов зависит от конкретной платформы • Не рекомендуется слишком полагаться на приоритеты (эффективность зависит от ОС, если она поддерживает приоритеты) • Выставление высоких приоритетов у нескольких потоков может привести с тому, что поток с низким приоритетом не получит процессорного времени © 2013 Net. Cracker Technology Corporation Confidential 10
План лекции • Многозадачность (multithreading) и Java API • Одновременный доступ (concurrency) и синхронизация • • • Проблемы одновременного доступа Синхронизация и ее недостатки Операции, не требующие синхронизации Блокирующие операции Монитор • Java Concurrency API © 2013 Net. Cracker Technology Corporation Confidential 11
Проблемы одновременного доступа • При неконтролируемом доступе разными потоками данные могут быть повреждены. • Race condition – ошибка проектирования многозадачной системы, при которой работа системы зависит от того, в каком порядке выполняются части кода. Состояние гонки — специфический баг, проявляющийся в случайные моменты времени и «затихающий» при попытке его локализовать. • В многопроцессорных системах необходима подгрузка разделяемых значений в память потока и запись в общую память. • Критическая секция – часть программы, в которой осуществляется доступ к разделяемым данным. Должна одновременно исполняться не более, чем одним потоком. © 2013 Net. Cracker Technology Corporation Confidential 12
Синхронизация • Синхронизированный блок synchronized (some. Obj /*объект синхронизации*/){ //при входе в блокируется объект some. Obj //тело блока } • Синхронизированный метод public synchronized void some. Method (){ /*при входе в метод блокируется объект (запрет вызова любого синхронизированного метода объекта)*/ //тело метода } Эквивалентный код: public void some. Method (){ synchronized(this){ //тело метода } } Cтатические методы синхронизуются по объекту-классу (Some. Class. class) © 2013 Net. Cracker Technology Corporation Confidential 13
Недостатки синхронизации • Невозможно прервать поток, пытающийся получить блокировку. • Невозможно задать тайм-аут для операции получения блокировки. • В некоторых случаях единственное условие на операцию блокировки неэффективно. • Примитивы JVM не всегда эффективно отображаются в возможности ОС. Издержки синхронизации • Механизм синхронизации весьма дорогостоящий (понижает скорость). • Дополнительный внутренний учетный код. Синхронизацию рекомендуется использовать лишь там, где это нужно © 2013 Net. Cracker Technology Corporation Confidential 14
Операции, не требующие синхронизации • Атомарные операции. Все операции над числами примитивного типа. • Операции с полями типа final. • Операции с полями типа volatile всегда атомарные • При чтение значения volatile-переменной оно всегда читается из общей памяти. • При записи значения volatile-переменной оно всегда пишется в общую память. • Обращение к volatile переменным занимает больше времени (однако это не так расточительно как дополнительный блок synchronized). • Операции над данными, доступными по volatile ссылке, могут быть не атомарны! © 2013 Net. Cracker Technology Corporation Confidential 15
Блокирующие операции • Блокирующие вызовы (IO, network, …) внутри synchronized методов. • При вызове sleep() ресурсы, монопольно используемые текущим потоком, остаются недоступными для других. • Взаимные блокировки (deadlocks) – остановка потоков из-за взаимозависимости между общими синхронизированными ресурсами; выявляются трудно. // Class A synchronized public void method. A (B b) { b. method. B(this); } // Class B synchronized public void method. B (A a) { a. method. A(this); } © 2013 Net. Cracker Technology Corporation Confidential 16
Монитор • Монитор (по определению) – объект класса, содержащего только закрытые поля. Но у мониторов Java поля необязательно закрытые. • Любой Java-объект может быть монитором. • Для взаимодействия с монитором поток должен иметь блокировку на него (синхронизироваться по нему). • Методы монитора (класс Object): wait(), wait(time) – ожидание монитора. notify() – извещение одного из ждущих потоков (произвольного). notify. All() – извещение всех ждущих потоков • Для работы с монитором поток должен им владеть (т. е. исполнять код, синхронизованный по данному объекту) © 2013 Net. Cracker Technology Corporation Confidential 17
План лекции • Многозадачность (multithreading) и Java API • Одновременный доступ (concurrency) и синхронизация • Java Concurrency API © 2013 Net. Cracker Technology Corporation Confidential 18
Java Concurrency API В Java 5 добавлены новые инструменты синхронизации (пакет java. util. concurrent), в том числе: 1. Набор классов для атомарных операций с объектами (java. util. concurrent. atomic) 2. Новые инструменты работы с блокировками (java. util. concurrent. locks) 3. Синхронизованные аналоги некоторых классов из пакета java. util © 2013 Net. Cracker Technology Corporation Confidential 19
java. util. concurrent. atomic Набор классов с атомарными методами • Atomic. Reference • Atomic. Integer • … Основной метод всех этих классов: <V> boolean compare. And. Set (V expected, V update) Атомарно проставляет новое значение, если текущее значение равно ожидаемому. Возвращает результат выполнения операции (успех/неудача). Метод реализуется через соответствующую инструкцию процессора, поэтому его грамотное использование позволяет повысить производительность по сравнению с блокировками. Кроме общих методов, некоторые классы предоставляют атомарные реализации специфических методов. © 2013 Net. Cracker Technology Corporation Confidential 20
java. util. concurrent. atomic – пример На основе классов пакета можно разрабатывать неблокирующие алгоритмы. К примеру, реализация метода Atomic. Integer. increment. And. Get: public final int increment. And. Get () { for (; ; ) { int current = get (); int next = current + 1; if (compare. And. Set (current, next)) return next; } } © 2013 Net. Cracker Technology Corporation Confidential 21
java. util. concurrent. locks. Lock Расширенный функционал по сравнению с использованием synchronized. Простейший пример использования: Lock l =. . . ; //Создание объекта блокировки l. lock (); //Захват блокировки try { //Код, защищенный блокировкой } finally { l. unlock (); //Снятие блокировки } Более сложный пример: Lock lock =. . . ; //Создание объекта блокировки if (lock. try. Lock ()) {//Попытка захватить блокировку try { //Код, защищенный блокировкой } finally { lock. unlock (); //Снятие блокировки } } else { //Альтернативные действия } © 2013 Net. Cracker Technology Corporation Confidential 22
java. util. concurrent. locks. Condition Аналог монитора. С каждым Condition объектом связан Lock, необходимый для работы с Condition-ом. /** * Очередь элементов ограниченной емкости * с атомарными операциями */ class Bounded. Queue { //Блокировка для синхронизации доступа к данным final Lock lock = new Reentrant. Lock (); //Сигнализирует о наличии свободного места final Condition not. Full = lock. new. Condition (); //Сигнализирует о наличии элементов final Condition not. Empty = lock. new. Condition (); //Данные, доступ к которым надо синхронизовать final Object[] items = new Object[100]; int putptr, takeptr, count; © 2013 Net. Cracker Technology Corporation Confidential 23
java. util. concurrent. locks. Condition /** * Добавляет элемент в конец очереди */ public void put (Object x) throws Interrupted. Exception { lock (); //Получение блокировки try { //Ожидание появления свободного места /* При входе в метод await блокировка атомарно снимается и поток усыпляется. После пробуждения перед выходом из метода блокировка восстанавливается. Цикл по условию необходимости ожидания нужен из-за паразитных пробуждений. */ while (count == items. length) not. Full. await (); items[putptr] = x; if (++putptr == items. length) putptr = 0; ++count; not. Empty. signal (); //Очередь теперь не пуста } finally { lock. unlock (); //Снятие блокировки } } © 2013 Net. Cracker Technology Corporation Confidential 24
java. util. concurrent. locks. Condition /** * Вынимает из очереди первый элемент */ public Object take () throws Interrupted. Exception { lock (); //Получение блокировки try { //Ожидание появления нового элемента while (count == 0) not. Empty. await (); Object x = items[takeptr]; if (++takeptr == items. length) takeptr = 0; --count; not. Full. signal (); //В очереди есть место return x; } finally { lock. unlock(); //Снятие блокировки } } } © 2013 Net. Cracker Technology Corporation Confidential 25
Что еще почитать • Хорстманн К. С. , Корнелл Г. – Java, том 2, глава 1 • API References for java. util. concurrent: http: //download. oracle. com/javase/7/docs/api/java /util/concurrent/package-summary. html • Введение в неблокирующие алгоритмы: http: //www. ibm. com/developerworks/ru/library/jjtp 04186/ © 2013 Net. Cracker Technology Corporation Confidential 26
09-Threads,Concurrency.pptx