Lecture11 (1133568), страница 6
Текст из файла (страница 6)
Синхронизация позволяетсогласовывать их действия и аккуратно передавать данные, полученные в одном потоке, в другой.И недостаточная синхронизация, и избыточная приводят к серьезным проблемам. Принедостаточной синхронизации один поток может начать работать с данными, которые ещенаходятся в обработке у другого, что приведет к некорректным итоговым результатам. Приизбыточной синхронизации как минимум производительность приложения может оказатьсяслишком низкой, а в большинстве случаев приложение просто не будет работать из-завозникновения тупиковых ситуаций (deadlocks), в которых два или более потоков не могутпродолжать работу, поскольку ожидают друг от друга освобождения необходимых им ресурсов.В обоих языках имеются конструкции, которые реализуют синхронизационный примитив,называемый монитором (monitor).
Монитор представляет собой объект, позволяющий потокам«захватывать» и «отпускать» себя. Только один поток может «держать» монитор в некоторыймомент времени — все остальные, попытавшиеся захватить монитор после его захвата этимпотоком, будут приостановлены до тех пор, пока этот поток не отпустит монитор.Для синхронизации используется конструкция, гарантирующая, что некоторый участок кода вкаждый момент времени выполняется не более чем одним потоком.
В начале этого участка нужнозахватить некоторый монитор, в качестве которого может выступать любой объект ссылочноготипа, в конце — отпустить его. Такой участок помещается в блок (или представляется в видеодной инструкции), которому предшествует указание объекта-монитора с ключевым словомsynchronized в Java или lock в C#.using System;using System.Threading;public class PingPong extends Thread{boolean odd;PingPong (boolean odd){ this.odd = odd; }public class PingPong{bool odd;PingPong (bool odd) { this.odd = odd; }static int counter = 1;static Object monitor = new Object();static int counter = 1;static object monitor = new object();public void run(){while(counter < 100){synchronized(monitor){if(counter%2 == 1 && odd){System.out.print("Ping ");counter++;}if(counter%2 == 0 && !odd){System.out.print("Pong ");counter++;}}}}public void Run(){while(counter < 100){lock(monitor){if(counter%2 == 1 && odd){Console.Write("Ping ");counter++;}if(counter%2 == 0 && !odd){Console.Write("Pong ");counter++;}}}}public static void main(String[] args){Thread th1 = new PingPong (false),th2 = new PingPong (true);public static void Main(){Thread th1 = new Thread(new ThreadStart(new PingPong(false).Run)),th2 = new Thread(new ThreadStart(new PingPong(true).Run));th1.start();th2.start();}}th1.Start();th2.Start();}}Кроме того, в Java любой метод класса можетбыть помечен как synchronized.
Это значит,что не более чем один поток может выполнятьэтот метод в каждый момент времени в рамкахобъекта, если метод нестатический и в рамкахвсего класса, если он статический.Такой модификатор эквивалентен помещениювсего тела метода в блок, синхронизированныйпо объекту this, если метод нестатический, аесли метод статический — по выражениюthis.getClass(), возвращающему объект,который представляет класс данного объекта.В Java также имеется стандартный механизмиспользования любого объекта ссылочного типав качестве монитора для создания болеесложных механизмов синхронизации.Для этого в классе java.lang.Object имеютсяметоды wait(), приостанавливающие текущийпоток до тех пор, пока другой поток не вызоветметод notify() или notifyAll() в том жеобъекте, или пока не пройдет указанное время.Все эти методы должны вызываться в блоке,синхронизированном по данному объекту.Однако это механизм достаточно сложен виспользовании и не очень эффективен.
Дляреализации более сложной синхронизациилучше пользоваться библиотечными классамииз пакетов java.util.concurrent иjava.util.concurrent.locks, появившихся вJDK версии 5 (см. ниже).БиблиотекиОбе платформы, как Java, так и .NET, в большой степени опираются на библиотеки готовыхкомпонентов. Сообщество разработчиков ведет постоянную работу по выработке стандартныхинтерфейсов компонентов для решения различных задач в разных предметных областях.
Подостижении определенной степени зрелости такие интерфейсы включаются в стандартныебиблиотеки.Для Java этот процесс начался значительно раньше и захватил гораздо больше участников всилу более раннего появления платформы и ее большей открытости и стандартизованности.Поэтому далеко не все часто используемые библиотеки классов распространяются в составеплатформ J2SE и J2EE. Разработка библиотек .NET ведется, в основном, силами программистов,работающих в Microsoft и некоторых ее партнерах.В данном разделе дается краткий обзор основных библиотек, подробности см.
в [10] и [11].Основные классы языка Java содержатся впакете java.lang.Базовым классом для всех ссылочных типовJava служит класс java.lang.Object.Этот класс содержит следующие методы.boolean equals(Object) — предназначен длясравнения объектов с учетом их внутреннихданных, перегружается в наследниках. В классеObject сравнивает объекты на совпадение.int hashCode() — возвращает хэш код данногообъекта, используется в хэширующихколлекциях. Должен перегружатьсяодновременно с методом equals().String toString() — преобразует данныйобъект в строку, перегружается в наследниках.Основные классы C# содержатся в пространствеимен System в сборке mscorlib.Базовым типом для всех типов C# служит классSystem.Object, который также имеет имяobject.bool Equals(object) — аналог методаequals() в Java.static bool Equals(object, object) —сравнивает два объекта с помощью Equals()или на равенство обеих ссылок null.static bool ReferenceEquals(object,object) — сравнивает ссылки на заданныеобъекты.int GetHashCode() — аналог методаhashCode() в Java.
Должен перегружатьсяВ классе Object выдает строку из имени классаи уникального кода объекта в JVM.Class<? extends Object> getClass() —возвращает объект, представляющий классданного объекта.protected void finalize() — вызываетсясборщиком мусора на одном из этапов удаленияобъекта из памяти. Может быть перегружен.protected Object clone() — предназначендля построения копий данного объекта,перегружается в наследниках. В классе Objectкопирует поля данного объекта в новый, есликласс данного объекта реализует интерфейсjava.lang.Cloneable, иначе выбрасываетисключение.void wait(), void wait(long timeout), voidwait(long timeout, int nanos) — методы,приостанавливающие выполнение текущегопотока до вызова notify() или notifyAll()другим потоком в данном объекте или доистечения заданного интервала времени.void notify(), void notifyAll() — методы,оповещающие потоки, которые ждутоповещения по данному объекту.
Первый метод«отпускает» только один из ждущих потоков,второй — все.Класс System предоставляет доступ кэлементам среды выполнения программы и рядполезных утилит. Все его элементы —статические.Поля in, out и err в этом классе представляютсобой ссылки на стандартные потоки ввода,вывода и вывода информации об ошибках. Онимогут быть изменены при помощи методовsetIn(), setOut() и setErr().Методы long currentTimeMillis() и longnanoTime() служат для получения текущегозначения времени.void exit(int status) — прекращаетвыполнение Java машины, возвращая указанноечисло внешней среде в качестве кода выхода.void gc() — запускает сборку мусора.
Времяот времени сборка мусора запускается исамостоятельно.Методы getenv(), getProperties() иgetProperty() служат для получения текущихзначений переменных окружения и свойств Javaмашины, задаваемых ей при запуске с опцией –d.одновременно с методом Equals().string ToString() — аналог методаtoString() в Java. В object выдает только имятипа данного объекта.System.Type GetType() — возвращает объект,представляющий тип данного объекта.protected object MemebrwiseClone() —создает копию данного объекта, имеющую теже значения всех полей.Данные о среде выполнения можно получить спомощью класса Environment.В нем имеются методыGetEnvironmentVariables() иGetEnvironmentVariable() для получениязначений переменных окружения, методы дляполучения командной строки, метод Exit(int)для прекращения работы текущего процесса,свойства с данными о машине и текущемпользователе, свойство TickCount, хранящееколичество миллисекунд с момента запускасистемы, и пр.Управлять стандартным вводом-выводомможно с помощью класса Console.Он содержит свойства In, Out, Err, методы длячтения из потока стандартного ввода и длязаписи в поток стандартного вывода, а такжемного других свойств консоли.load(), loadLibrary() — служат для загрузкибиблиотек, например, реализующих nativeинтерфейсы.void arraycopy() — используется длябыстрого копирования массивов.int identityHashCode(Object) — возвращаетуникальный числовой идентификатор данногообъекта в Java машине.Другой класс, содержащий методы работы сосредой выполнения, — Runtime.Для работы со строками используются классыString, StringBuffer и StringBuilder(последний появился в Java 5).