13.3 Многопоточность и синхронизация

Java, по-видимому, является единственным универсальным языком программирования, в котором механизмы создания нитей поддерживаются встроенными средствами языка. В традиционных языках программирования (например, C) создание нитей обеспечивается системно-зависимыми библиотеками, обеспечивающими API ОС. В Java средства создания нитей системно-независимые.

В Java-программе нить представляет отдельный класс, который может быть создан

либо как подкласс (наследник) суперкласса Tread;

либо как класс, реализующий интерфейс Runnable, внутри этого класса должна быть переменная экземпляра класса - ссылка на объект класса Tread.

Суперкласс Tread и интерфейс Runnable определены в базовой библиотеке языка Java - пакете java.lang. При любом варианте создания в классе-нити должен быть реализован метод run(). Выполнение метода start() для экземпляра такого класса вызывает выполнения метода run() в отдельном потоке вычисления.

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

Но Java VM не выполняет действий по планированию нитей на выполнение. Для этого библиотечные методы Java обращаются к ОС, используя API той ОС, в среде которой работает Java VM.

Для нитей в Java предусмотрено управление приоритетами (методы getPriority(), setPriority()), однако, и здесь Java использует механизмы управления приоритетами ОС. Так, уже классическим для учебников по Java является пример аплета, в котором по экрану "наперегонки" движутся несколько объектов, движение каждого осуществляется в отдельной нити и с собственным приоритетом. Этот пример весьма наглядно демонстрируется в средах, например, OS/2 и Linux, но выглядит не очень убедительным в среде Windows 95/98, так как приоритет нити не слишком влияет на скорость движения объекта - примерно так, как показано на рисунке 13.5.

 

Рисунок 13.5 "Гонки" в разных операционных средах (движение справа налево).

Любая нить может быть сделана нитью-"демоном". Нить-"демон" продолжает выполняться даже после окончания той нити, в которой она была создана. Нить становится "демоном" при ее создании только в том случае, если она создается из нити-"демона". Программа может изменить состояния нити при помощи метода setDaemon() класса Thread. Выполнение любой программы Java VM начинает с единственной нити (в которой вызывается метод main()), и эта нить запускается не как "демон". Java VM продолжает существовать, пока не завершатся все нити не-"демоны".

В языке Java имеется также класс ThreadGroup - группа нитей, которая может управляться совместно.

Если в Java предусмотрены нити, то, естественно, должны быть предусмотрены и средства синхронизации и взаимного исключения при параллельной работе нитей. Основным средством синхронизации и взаимного исключения в Java является ключевое слово synchronized, которое может употребляться перед каким-либо программным блоком. Ключевое слово synchronized определяет невозможность использования программного блока двумя или более нитей одновременно. В Java synchronized-блоки называются мониторами и их фактическая тождественность мониторам Хоара, описанным в разделе 8.8 части I, очевидна. В зависимости от деталей способа употребления synchronized может работать как:

защищенная (guard - см. раздел 8.8 части I) процедура - в том случае, если synchronized-блок представляет собой целый метод, однако, в отличие от описанных нами guard-процедур одновременное вхождение в разные synchronized-методы возможно;

анонимные скобки критической секции - в том случае, если synchronized-блок является просто программным блоком;

скобки критической секции с защитой выбранного ресурса - в том случае, если после ключевого слова synchronized указывается в скобках ссылка на объект.

В первоначальной версии языка Java для класса Thread предусмотрены методы:

resume() - приостановить выполнение нити;

suspend() - возобновить выполнение нити;

yeld() - сделать паузу в выполнении нити, чтобы дать возможность выполниться другой нити;

join() - ожидать завершения нити.

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

Класс Object имеет три метода:

wait() - ожидать уведомления об этом объекте;

notify() - послать уведомление одной из нитей, ждущих уведомления об этом объекте;

notifyAll() - послать уведомление всем из нитям, ждущим уведомления об этом объекте.

Поскольку класс Object является корнем иерархии классов, объекты всех - стандартных и пользовательских - классов являются его подклассами и наследуют эти методы. Эти методы аналогичны операциям wait и signal, описанным нами в разделе 8.7 части I. Реализация, например, общего (с возможным значением, большим 1) семафора с использованием этих средств будет выглядеть следующим образом:

 //** семафор реализуется в виде класса Semaphore

 public class Semaphore

 {

 // значение семафора

 private int Semaphore_value;

 //** пустой конструктор семафора, по умолчанию начальное значение семафора - 0

 public Semaphore()

 {

 this(0);

 }

 //** конструктор с параметром - начальным значением семафора,

 // если задано отрицательное значение, устанавливается начальное значение 0

 public Semaphore(int val)

 {

 if (val < 0) Semaphore_value = 0

 else Semaphore_value = val;

 }

 //** V-операция. V- и P-операции объявлены synchronized,

 // чтобы исключить одновременное выполнение их двумя или более нитями

 public synchronized void V()

 {

 // возможно пробуждает нить, ожидающую у семафора

 if (Semaphore_value == 0) this.notify();

 // увеличивает значение семафора

 Semaphore_value++;

 }

 //** P-операция

 public synchronized void P() throws InterruptedException

 // исключение может выбрасываться в wait

 {

 // если значение семафора равно 0, блокирует нить

 while (counter == 0) this.wait();

 // уменьшает значение семафора

 Semaphore_value--;

 }

 }

В Java VM с каждым объектом связывается замок (lock) и список ожидания (wait set).

В спецификациях байт-кода Java имеются специальные команды monitorenter и monitorexit, устанавливающие и снимающие замок. Java VM, входя в synchronized-блок, пытается выполнить операцию установки замка и не продолжает выполнения нити, пока операция не будет выполнена. При выходе из synchronized-блока выполняется операция снятия замка.

Список ожидания используется методами wait(), notify(), notifyAll(). Он представляет собой список нитей, ожидающих уведомления о данном объекте. Названные операции работают с этим списком очевидным образом.

Следует отметить, что многопоточность, заложенная в языке Java, имеет большие перспективы. Изначально сама идея нитей (а ее первая коммерческая реализация была сделана именно фирмой Sun Microsystems) возникла как решение, призванное обеспечить эффективную загрузку оборудования в многопроцессорных системах, но теперь свойства многопоточности, закладываемые в программное обеспечение, оказывают (наряду с другими факторами) обратное влияние на процессорные архитектуры, стимулируя развитие в них средств распараллеливания вычислительного процесса.

Так, новый проект компьютерной архитектуры фирмы Sun Microsystems носит название MAJC (Microprocessor Architecture for Java Computing - архитектура микропроцессора для Java-вычислений), которое говорит само за себя. В концепцию этой архитектуры (как, впрочем, и ряда других новых архитектур) входит многопроцессорная обработка с несколькими "потоковыми устройствами" в каждом процессоре. Такая архитектура призвана обеспечить более эффективную обработку на сетевом сервере современных потоков данных, которые характеризуются возрастанием удельного веса в них мультимедийной информации.

Для получения лучшей производительности, кроме многопоточных микропроцессоров, разработчики MAJC применяют технологию, называемую "пространственно-временными вычислениями" или "предположительной многопоточности". В этой технологии прикладной программист вообще не будет беспокоиться о распараллеливании своих программ, потому что эта работа будет сделана за него Java VM.

Смысл пространственно-временных вычислений сводится к следующему. Java VM проверяет программу и предполагает, что два метода могут выполняться одновременно на двух процессорах. Она посылает метод A на первый процессор, а метод B - на второй для предположительного вычисления. Поскольку B - предположительный метод, он выполняется в отдельном адресном пространстве, называемом предположительной памятью. Если все идет хорошо, и никакие зависимости в данных не нарушены, то предположительная память сливается с основной памятью и программа обрабатывает следующую пару методов. Если произошло нарушение, то второй метод отменяется и предположительная память "выбрасывается".

Идея пространственно-временных вычислений не является кардинально новой, но она не применялась в обычных многопроцессорных системах без многопоточности, так как позволяла увеличить эффективность выполнения программ в 2-процессорной конфигурации не более, чем на 5%. Разработчики MAJC рассчитывают, что в их архитектуре производительность последовательных приложений на двух процессорах должна возрасти в 1.6 раза.


Информация о работе «Операционные системы "тонких" клиентов»
Раздел: Информатика, программирование
Количество знаков с пробелами: 257667
Количество таблиц: 0
Количество изображений: 26

Похожие работы

Скачать
129632
2
0

... , выдачей и приёмом лицензий). В условиях крупных сетей рекомендуется выделение под сервер лицензий отдельного компьютера (или нескольких - для резервирования). 1.1 Архитектура терминальных устройств В компьютерных технологиях трёхуровневая архитектура, синоним трёхзвенная архитектура (по англ. three-tier или Multitier architecture) предполагает наличие следующих компонентов приложения: ...

Скачать
116709
11
1

... ФС в разделе MS-DOS. Это конфигурационный файл в котором содержится информация о драйверах используемых в процессе запуска ФС. Пункт доступен супервизору или его эквивалентам. «Система учета» NetWare обладает очень гибкой системой учета ресурсов, предоставляемых в общее пользование. Используя данный пункт меню можно просмотреть, а так же имея определенные права настроить плату за использование ...

Скачать
41540
0
0

... числе на промышленных предприятиях, больше подходят клиент-серверные СУБД. Мы рассмотрим особенности таких распространенных СУБД, как Oracle и MS SQL Server. Глава 4. Язык SQL в системах управления базами данных SQL (англ. Structured Query Language — язык структурированных запросов) — универсальный компьютерный язык, применяемый для создания, модификации и управления данными в реляционных ...

Скачать
111441
18
8

... ОС Windows 95, необходимость выбора тех конкретных объектов, к которым необходимо ограничить доступ. Настоящая работа посвящена разработке программы защиты объектов операционной системы WINDOWS95 работающей в многопользовательском режиме под управлением сервера Novell NetWare (Windows NT, Unix), позволяющей проводить защиту объектов ОС на уровне пользователя. Под защитой объектов ОС Windows 95 ...

0 комментариев


Наверх