Тимур Машнин - Многопоточное программирование в Java
- Название:Многопоточное программирование в Java
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:9785005314642
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Тимур Машнин - Многопоточное программирование в Java краткое содержание
Многопоточное программирование в Java - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Поэтому задача не сможет распечатать все десять чисел от 0 до 9.
Для запроса на прерывание потока, основной поток вызывает метод прерывания interrupt.
В Java один поток не может просто остановить другой поток.
Поток может только запросить остановку другого потока.
И запрос выполняется в виде вызова метода interrupt.
Вызов метода interrupt в экземпляре Thread устанавливает флаг прерывания как true.
Если этот поток заблокирован вызовом методов wait, join или sleep, то его статус прерывания будет очищен, и он выбросит исключение InterruptedException.
Таким образом, как только taskThread прерывается основным потоком, Thread.sleep (1000) отвечает на прерывание, выбрасывая исключение.
Исключение InterruptedException обрабатывается, прерывая цикл и тем самым заканчивая задачу раньше.
Таким образом, чтобы задача немедленно реагировала на запрос прерывания, можно использовать обработку исключения InterruptedException.
После очистки статуса прерывания, подтвердить этот статус можно самопрерыванием с помощью вызова Thread.currentThread().interrupt ().

И без использования обработки InterruptedException, прервать цикл задачи можно, проверяя статус прерывания с помощью вызова Thread.isInterrupted ().
Синхронизация потоков

Теперь, когда мы рассмотрели потоки, давайте разберем ключевую концепцию в многопоточном программировании, которая идет рука об руку с потоками, и это блокировки.
Потоки взаимодействуют между собой, главным образом, путем совместного доступа к полям объектов.
Это взаимодействие делает возможными два вида ошибок: интерференция потоков и ошибки согласованности памяти.
Предположим, что у нас есть очень простой метод объекта, который принимает число и увеличивает его на единицу.

Другой метод этого объекта уменьшает это число на единицу.
Предположим, есть два потока T1 и T2, и один поток хочет увеличить число, а другой поток хочет уменьшить число.
Эти два потока могут быть запланированы на двух разных ядрах, и они могут читать и записывать поле объекта в одно и то же время, и результат будет непредсказуемым.
При одновременной записи возникнет интерференция потоков.
А при одновременной записи и чтении возникнет ошибка согласованности памяти.
Как нам избежать ситуации, когда два потока хотят получить доступ к одному и тому же объекту одновременно?
Для этого используется блокировка.
Java обеспечивает блокировки для защиты определенных частей кода, которые будут выполняться несколькими потоками одновременно.
Самый простой способ блокировки определенного метода – это определить метод с ключевым словом synchronized.
Ключевое слово synchronized в Java обеспечивает:

Что только один поток может одновременно выполнять блок кода
Что каждый поток, входящий в синхронизированный блок кода, видит результаты всех предыдущих модификаций, которые были защищены одной и той же блокировкой.
Синхронизация необходима для взаимоисключающего доступа к блокам и для надежной связи между потоками.
Синхронизация метода обеспечивает, что, когда один поток выполняет синхронизированный метод объекта, все другие потоки, которые вызывают синхронизированные методы этого объекта приостанавливают выполнение до тех пор, пока первый поток не закончит свою работу с объектом.
Когда синхронизированный метод завершится, он автоматически установит причинно-следственную связь для последующего вызова синхронизированного метода этого объекта.
Это гарантирует, что изменения состояния объекта будут видны для всех потоков.
Когда поток вызывает синхронизированный метод, он автоматически получает внутреннюю блокировку для объекта этого метода и освобождает его при возврате метода.
Освобождение блокировки происходит, даже если возврат метода был вызван неперехваченным исключением.
Другими словами, каждый объект в Java имеет ассоциированный с ним монитор.
Монитор представляет своего рода инструмент для управления доступа к объекту.
Когда выполнение кода доходит до оператора synchronized, монитор объекта захватывается владельцем, и на это время монопольный доступ к синхронизированному коду имеет только один поток, который является владельцем монитора.
После окончания работы блока кода, монитор объекта освобождается и становится доступным для других потоков.
Когда вызывается статический синхронизированный метод, так как статический метод связан с классом, а не с объектом, в этом случае поток получает блокировку для объекта Class, связанного с классом и представляющего класс в среде выполнения.
Таким образом, доступ к синхронизированным статическим полям класса контролируется блокировкой, отличной от блокировки для любого экземпляра класса. Поэтому статические синхронизированные методы и нестатические синхронизированные методы никогда не заблокируют друг друга.
Конструкторы не могут быть синхронизированы – использование ключевого слова synchronized для конструктора является синтаксической ошибкой.
Синхронизация конструктора не имеет смысла, потому что только поток, который создает объект, имеет доступ к нему во время его создания.
Еще раз, если два нестатических метода класса объявлены как synchronized, то в каждый момент времени из разных потоков на одном объекте может быть вызван только один из них.
Поток, который вызывает метод первым, захватит монитор, и второму потоку придется ждать.
Это верно только для разных потоков.
Один и тот же поток может вызвать синхронизированный метод, внутри него – другой синхронизированный метод на том же экземпляре. И это будет повторная блокировка.
Поскольку этот поток владеет монитором, проблем второй вызов не создаст.
Это верно только для вызовов методов одного экземпляра.
У разных экземпляров разные мониторы, поэтому одновременный вызов нестатических методов проблем не создаст.
Другой способ создания синхронизированного кода – синхронизированные блоки.
В отличие от синхронизированных методов, синхронизированные блоки должны указывать объект, который обеспечивает внутреннюю блокировку.

Когда один поток заходит внутрь блока кода, помеченного словом synchronized, то Java-машина тут же блокирует монитор объекта, который указан в круглых скобках после слова synchronized.
Читать дальшеИнтервал:
Закладка: