Совместное использование ресурсов
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

При многопоточной архитектуре приложения возможны ситуации, когда несколько потоков будут одновременно работать с одними и теми же данными, используя их значения и присваивая новые. В таком случае результат работы программы становится невозможным предопределить, глядя только на исходный код. Финальные значения переменных будут зависеть от случайных факторов, исходя из того, какой поток какое действие успел сделать первым или последним. Отсюда следует возможность некорректной работы алгоритма, возникновения исключительных ситуаций.

Решением проблемы является применение механизма блокировки объекта:

• Только один поток в один момент времени может установить блокировку на некоторый объект.

• Попытка блокировки уже заблокированного объекта приводит к останову потока до момента разблокирования этого объекта.

• Наличие блокировки не запрещает всех остальных действий с объектом.

Рисунок 5

В Java-программе для того, чтобы воспользоваться механизмом блокировок, существует ключевое слово synchronized. Оно может быть применено в двух вариантах – для объявления synchronized-блока и как модификатор метода. В обоих случаях действие его примерно одинаковое.

Синхронизированный блок:

//Блокируется указанный объект

synchronized ( ref < Ссылка на объект>)

{

      <Тело блока синхронизации>

}

Прежде чем начать выполнять действия, описанные в этом блоке, поток обязан установить блокировку на объект, на который ссылается переменная ref (поэтому она не может быть null). Если другой поток уже установил блокировку на этот объект, то выполнение первого потока приостанавливается до тех пор, пока не удастся выполнить блокировку. После этого блок выполняется. В случае успешного либо не успешного завершения исполнения, производится снятие блокировки, чтобы освободить объект для других потоков.

Synchronized-методы работают аналогичным образом. Прежде чем начать выполнять их, поток пытается заблокировать объект, у которого вызывается метод. После выполнения блокировка снимается.

Синхронизированный метод:

//Блокируется объект-владелец метода

public synchronized void <Имя метода>() {

      < Тело метода >

}

Характерные ошибки:

• Отсутствие синхронизации.

• Необоснованная длительная блокировка объектов.

• Взаимная блокировка (deadlock). Если один поток заблокировал один ресурс, и пытается заблокировать второй, а другой поток заблокировал второй и пытается заблокировать первый, то такие потоки уже никогда не выйдут из состояния ожидания. В Java нет никаких средств распознавания или предотвращения ситуаций deadlock. Также нет способа перед вызовом синхронизированного метода узнать, заблокирован ли уже объект другим потоком. Программист сам должен строить работу программы таким образом, чтобы неразрешимые блокировки не возникали.

• Возникновение монопольных потоков.

• Нерациональное назначение приоритетов.

Volatile

Рассмотрим пример 40.

Пример 40.

curentValue = 5;

for (;;){

display . showValue ( currentValue );

Thread . sleep (1000);

}

Если метод showValue сам по себе не обладает возможностью изменения значения curentValue, компилятор может предположить, что внутри цикла for это значение можно трактовать как неизменное, и использовать одну и ту же константу 5 на каждой итерации цикла при вызове showValue. Но если содержимое поля curentValue в ходе выполнения цикла подвержено обновлению посредством других потоков, предположение компилятора окажется неверным.

Преодолеть проблему может соответствующим способом оформленный синхронизированный код. Однако существует альтернативный вариант решения проблемы – объявление поля можно снабдить модификатором volatile. Этот признак свидетельствует о том, что значение поля может быть изменено в любой непредсказуемый момент. Если объявить curentValue как volatile, компилятор будет вынужден, выполняя каждую итерацию цикла, заново перечитывать значение переменной. Метод, выполняющий считывание содержимого переменной, обозначенной признаком volatile , гарантровано возвращает наиболее свежую версию сохраненного в ней значения.

Дата: 2019-02-19, просмотров: 209.