Главная » Java » ПОТОКИ вычислений Java

0

                                                   

                                                 Как -можно быть в двух -местах одновременно. не будучи нигде?

                            Firesign Theater

Инструкции программ, которые мы обычно пишем, выполняются шаг за шагом в строгой последовательности. Следующий рисунок иллюстрирует ситуацию, когда программа запрашивает значение текущего остатка на банковском счете (getBalance), выполняет приходную операцию, увеличивая остаток на сумму deposit,а затем сохраняет результат в объекте банковского счета (setBalance).

                                                                                              ?

                             bal = a.getBalance();

                                                                                              ?

                                  bal += deposit;

                                                                                              ?

                               a.setBalance(bal);

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

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

 

            ?                                       ?

      bal = a.getBalance();                                                                       bal = b.getBalance();

                               ?                                       ?

        bal += deposit;                                                                                                  bal += deposit;

                               ?                                       ?

       a.setBalance(bal);                                                                            b.setBalance(bal);

                                      

 

Программа, отображающая последовательности одновременных действий нескольких кассиров, реализует модель многопоточных вычислений. Поток в программе, как и кассир в банке, способен решать свою собственную задачу независимо от других потоков (кассиров). И поскольку два кассира могут пользоваться одним и тем же шкафом с картотекой, точно так же два потока в программе вправе обращаться к одним объектам.

Разделение доступа к объектам – это одновременно и наиболее Мощный и плодотворный инструмент многопоточного программирования, и самый серьезный источник недоразумений и ошибок. Схема действий "запросить-изменить-сохранить данные" сопряжена с так называемыми условиями состязаний (race conditions), которые имеют место в тех случаях, когда два потока способны поочередно изменять одну и ту же порцию данных, рискуя нарушить их целостность. Продолжим пример, касающийся изменения состояния банковского счета, и представим, что владелец счета обратился к кассиру с просьбой принять некоторую сумму денег и пополнить остаток. Почти в то же самое время к другому кассиру направился совладелец того же счета и потребовал выполнить собственную приходную операцию.

 

            ?                                       ?

      bal1 = a.getBalance();                                                                    bal 2= b.getBalance();

                               ?                                       ?

        bal1 += deposit;                                                                                bal2 += deposit;

                               ?                                       ?

       a.setBalance(bal1);                                                                          b.setBalance(bal2);

Оба кассира проследовали к картотеке, заглянули в одну и ту же папку и получили совершенно одинаковую информацию о текущем остатке на счете (мы говорим, разумеется, о банке, который работает по старинке, используя бумажные технологии). Затем кассиры возвратились к своим стойкам, приняли вклады и вернулись к шкафу с папками, чтобы зафиксировать раздельно выполненные ими операции. Если следовать подобной логике, на состояние остатка повлияет только последняя из двух операций – результат первой будет попросту утрачен.

В банке подобная проблема может быть решена следующим образом: кассир, обратившийся к папке первым, обязан поместить в нее закладку с запиской примерно такого содержания: "Я работаю с этим счетом; подождите, пока не закончу". Практически то же самое делается и в многопоточной программе: объект обозначается признаком блокировки (lock), свидетельствующим о том, что использовать объект запрещено.

Многие реальные задачи могут быть наилучшим образом решены именно в рамках много поточной модели. Например, интерактивные графические программы часто нуждаются в том, чтобы пользователь имел возможность вмешиваться в процесс вычислений в любой момент. Наиболее эффективное средство достижения такой цели связано с использованием нескольких потоков. Напротив, однопоточные системы способны лишь к созданию иллюзии одновременных вычислений; для этого в них используются различные механизмы прерывания по вызову (polling), которые предоставляют поочередный доступ к ресурсам компьютера нескольким частям приложения. В частности, та область кода программы, которая ответственна за графический вывод, должна быть написана таким образом, чтобы ее можно было прерывать настолько часто, насколько это необходимо для обеспечения быстрой реакции системы на действия пользователя.

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

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

В этой главе описаны языковые конструкции, классы и методы, позволяющие управлять потоками вычислений в Jаvа-программе. Впрочем, это не значит; что нашего материала совершенно достаточно для приобретения знаний и навыков создания эффективных многопоточных программных приложений. За дополнительной, более полной информацией по подобным вопросам вы можете обратиться, например, к другой из книг этой серии – Concurrent Programming in Java™. Заключительный раздел, Список литературы, нашей книги содержит ссылки на другие полезные информационные источники, имеющие отношение к модели многопоточности и синхронизации в Java.

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии