Читаем Многопоточное программирование в Java полностью

Теперь предположим, что вы приобрели блокировку чтения, и после успешного чтения вы хотели изменить значение.

Для этого вам понадобится блокировка записи, которую вы можете получить с помощью метода tryConvertToWriteLock.

Следует отметить, что методы tryConvertToReadLock и tryConvertToWriteLock могут не заблокировать и вернуть штамп как ноль, а это значит, что вызовы этих методов не были успешными.

Метод tryConvertToOptimisticRead освобождает блокировку и возвращает штамп для наблюдения.

Также нужно отметить, что планировщик потоков в случае StampedLock не всегда предпочитает читателей над писателями или наоборот.

Приоритеты потоков


Для потоков мы можем устанавливать приоритеты с помощью метода setPriority класса Thread.

Установив приоритет потока выше, мы сигнализируем, что этот поток должен получить больше процессорного времени, чем потоки с более низким приоритетом.

Установка приоритета потоков не гарантирует, что поток фактически получит больше процессорного времени, так как другие факторы, такие как ожидание ресурсов, могут влиять на производительность потока с более высоким приоритетом.

Также способ, которым базовая операционная система реализует многозадачность, также может влиять на производительность потоков, и поток с более низким приоритетом может в некоторых условиях фактически получать больше времени процессора, чем поток с более высоким приоритетом.

Но в общем, потоки с более высоким приоритетом получат больше процессорного времени, чем потоки с более низким приоритетом.

Существует три константы класса Thread, определяющие приоритет потока MIN_PRIORITY, NORM_PRIORITY и MAX_PRIORITY.



Атомарные переменные



Как мы увидели, ключевой задачей многопоточного программирования является управление доступом параллельных потоков к общим ресурсам.

И мы узнали об использовании блокировок различными способами.

В многопоточном программировании есть такое понятие, как критическая секция.



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

Предположим, у меня есть банковский счет.

И мой банковский счет, скажем, содержит 500 долларов.

И у меня есть общий банковский счет с дочерью.

Моя дочь имеет собственный банковский счет, баланс которого составляет 0 долларов.

Дочь просит у меня 100 долларов.

Я перевожу деньги со своего счета на общий счет, а дочка переводит деньги с общего счета на свой счет.

Теперь мы можем смоделировать эту операцию, используя два потока.

Есть поток T1, в котором 100 долларов вычитаются из моего баланса и добавляются к общему балансу.

И есть поток T2, где 100 долларов вычитаются из общего баланса и добавляются к балансу дочери.

Теперь вопрос в том, что может пойти не так, если это будет выполнено как многопоточная программа?

Мы видим, что здесь есть переменная общего баланса, которая читается и записывается двумя потоками.

При этом порядок чтения и записи этой общей переменной может вызвать проблемы.

Например, если чтение с одного потока вклинится между чтением и записью в другом потоке.

Поэтому эта переменная должна быть изолирована и находиться в критической секции.

Критические секции могут быть реализованы с помощью низкоуровневого или высокоуровневого интерфейса программирования.

Предположим, что у нас есть массив элементов.

И доступ к этим элементам осуществляется несколькими потоками.

И эти потоки извлекают элементы из массива и обрабатывают их.

Таким образом, каждый из этих потоков может выполнять цикл с переменной-счетчиком, которая отслеживает текущий элемент.

На каждом этапе цикла эта переменная увеличивается на единицу.

Если у вас несколько потоков, выполняющих этот код, мы уже определили проблемы, которые могут возникнуть.

В гонке потоков могут быть одновременные обращения к общей переменной и некорректная ее запись, и чтение.

Для устранения этой проблемы нужно изолировать эту переменную.

А обработка элементов может продолжаться параллельно.

Таким образом, нужно сделать переменную-счетчик атомарной.

Вместо того, чтобы реализовать это с помощью низкоуровневого программирования, и блокировать весь код, где используется эта переменная, мы можем воспользоваться пакетом java.util.concurrent.atomic, который определяет классы, поддерживающие атомарные операции для одиночных переменных.



И таким образом изолировать только эту переменную, а остальной код оставить параллельным.

При этом вместо синхронизации мы можем просто использовать объекты соответствующих классов.

Атомарные классы гарантируют выполнение определенных операций, таких как увеличение и уменьшение, обновление или добавление значения, потокобезопасным способом.



Пакет java.util.concurrent.atomic также предоставляет класс AtomicReference, который позволяет обновлять ссылку на объект атомарно.

Здесь мы на основе строки создаём объект AtomicReference, который позволяет обновить ссылку на строку атомарно.



Перейти на страницу:

Похожие книги

«Ага!» и его секреты
«Ага!» и его секреты

Вы бы не хотели, скажем, изобрести что-то или открыть новый физический закон, а то и сочинить поэму или написать концерт для фортепьяно с оркестром?Не плохо бы, верно? Только как это сделать? Говорят, Шиллер уверял, будто сочинять стихи ему помогает запах гнилых яблок. И потому, принимаясь за работу, всегда клал их в ящик письменного стола. А физик Гельмгольц поступал иначе. Разложив все мысленно по полочкам, он дожидался вечера и медленно поднимался на гору лесной дорогой. Во время такой прогулки приходило нужное решение.Словом, сколько умов, столько способов заставить мозг работать творчески. А нет ли каких-то строго научных правил? Одинаковы ли они для математиков, биологов, инженеров, поэтов, художников? Да и существуют ли такие приемы, или каждый должен полагаться на свои природные способности и капризы вдохновения?Это тем более важно знать, что теперь появились «электронные ньютоны» — машины, специальность которых делать открытия. Но их еще нужно учить.Решающее слово здесь принадлежит биологам: именно они должны давать рецепты инженерам. А биологи и сами знают о том, как мы думаем, далеко не все. Им предстоит еще активнее исследовать лабораторию нашего мышления.О том, как ведутся эти исследования, как постепенно «умнеют» машины, как они учатся и как их учат, — словом, о новой науке эвристике рассказывает эта книга.

Елена Викторовна Сапарина

Зарубежная компьютерная, околокомпьютерная литература
Создание трилогии BioShock. От Восторга до Колумбии
Создание трилогии BioShock. От Восторга до Колумбии

Всего за три игры сага BioShock заняла особое место в сердцах игроков. Она может похвастаться проработанными и совершенно уникальными персонажами и мирами. Действие первых двух частей происходит в подводном городе Восторг, где игрок погружается в стиль ар-деко и атмосферу 1950-х годов. Третья часть, BioShock Infinite, переносит вас в 1912 год и приглашает исследовать небесный город Колумбия в сеттинге стимпанка.В книге вас ждут:[ul]рассуждение об источниках вдохновения создателя серии Кена Левина;исследование уникального геймплея и механик;подробности разработки игр франшизы от идеи до выпуска;глубокий анализ сюжета, тем и персонажей каждой части.[/ul]Авторы отдают дань уважения популярной серии игр, которая, несмотря на короткую историю, уже получила признание критиков.В формате PDF A4 сохранен издательский макет книги.

Мехди Эль Канафи , Николя Курсье , Рафаэль Люка

Зарубежная компьютерная, околокомпьютерная литература