В.В. Кулямин - Технологии программирования. Компонентный подход (1133554), страница 55
Текст из файла (страница 55)
Синхронизация позволяетсогласовывать их действия и аккуратно передавать данные, полученные в одном потоке, в другой.И недостаточная синхронизация, и избыточная приводят к серьезным проблемам. Принедостаточной синхронизации один поток может начать работать с данными, которые еще199находятся в обработке у другого, что приведет к некорректным итоговым результатам. Приизбыточной синхронизации как минимум производительность приложения может оказатьсяслишком низкой, а в большинстве случаев приложение просто не будет работать из-завозникновения тупиковых ситуаций (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();200Кроме того, в 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) — предназначен длясравнения объектов с учетом их внутреннихданных, перегружается в наследниках.
В классеОсновные классы C# содержатся в пространствеимен System в сборке mscorlib.Базовым типом для всех типов C# служит классSystem.Object, который также имеет имяobject.bool Equals(object) — аналог методаequals() в Java.static bool Equals(object, object) —201сравнивает два объекта с помощью Equals()илина равенство обеих ссылок null.int hashCode() — возвращает хэш код данногоstatic bool ReferenceEquals(object,объекта, используется в хэширующихobject) — сравнивает ссылки на заданныеколлекциях. Должен перегружатьсяобъекты.одновременно с методом equals().int GetHashCode() — аналог методаString toString() — преобразует данныйhashCode() в Java. Должен перегружатьсяобъект в строку, перегружается в наследниках.В классе Object выдает строку из имени класса одновременно с методом Equals().и уникального кода объекта в JVM.string ToString() — аналог методаtoString() в Java.
В object выдает только имяClass<? extends Object> getClass() —типа данного объекта.возвращает объект, представляющий классданного объекта.System.Type GetType() — возвращает объект,представляющий тип данного объекта.protected void finalize() — вызываетсясборщиком мусора на одном из этапов удаления protected object MemebrwiseClone() —объекта из памяти. Может быть перегружен.создает копию данного объекта, имеющую теже значения всех полей.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 предоставляет доступ кэлементам среды выполнения программы и ряд помощью класса Environment.полезных утилит. Все его элементы —В нем имеются методыстатические.GetEnvironmentVariables() иПоля in, out и err в этом классе представляют GetEnvironmentVariable() для получениясобой ссылки на стандартные потоки ввода,значений переменных окружения, методы длявывода и вывода информации об ошибках.
Они получения командной строки, метод Exit(int)могут быть изменены при помощи методовдля прекращения работы текущего процесса,setIn(), setOut() и setErr().свойства с данными о машине и текущемпользователе, свойство TickCount, хранящееМетоды long currentTimeMillis() и longколичество миллисекунд с момента запускаnanoTime() служат для получения текущегосистемы, и пр.значения времени.Управлять стандартным вводом-выводомvoid exit(int status) — прекращаетвыполнение Java машины, возвращая указанное можно с помощью класса Console.число внешней среде в качестве кода выхода.Он содержит свойства In, Out, Err, методы длячтения из потока стандартного ввода и дляvoid gc() — запускает сборку мусора.
Времязаписив поток стандартного вывода, а такжеот времени сборка мусора запускается имного других свойств консоли.Object сравнивает объекты на совпадение.202самостоятельно.Методы getenv(), getProperties() иgetProperty() служат для получения текущихзначений переменных окружения и свойств Javaмашины, задаваемых ей при запуске с опцией –d.load(), loadLibrary() — служат для загрузкибиблиотек, например, реализующих nativeинтерфейсы.void arraycopy() — используется длябыстрого копирования массивов.int identityHashCode(Object) — возвращаетуникальный числовой идентификатор данногообъекта в Java машине.Другой класс, содержащий методы работы сосредой выполнения, — Runtime.Для работы со строками используются классыString, StringBuffer и StringBuilder(последний появился в Java 5).
Все ониреализуют интерфейс последовательностейсимволов CharSequence.Класс String представляет неизменяемыестроки, два других класса — изменяемые.Отличаются они тем, что все операцииStringBuffer синхронизованы, а операцииStringBuilder — нет. Соответственно, первыйкласс нужно использовать для представлениястрок, с которыми могут работать несколькопотоков, а второй — для повышенияпроизводительности в рамках одного потока.В пакете java.lang находятся классы-оберткипримитивных типов Boolean, Byte, Character,Short, Integer, Long, Float, Double.Все числовые классы наследуют классуjava.lang.Number.Эти классы содержат константы,представляющие крайние значениясоответствующих типов, методы дляпреобразования значений соответствующихтипов в строку и для получения этих значенийиз строк, а также методы для работы с битовымпредставлением значений числовых типов.Для форматированного представления чиселиспользуются классы java.text.NumberFormatи java.text.DecimalFormat.Набор математических функций и константреализован в виде элементов классаjava.lang.Math.Для генерации псевдослучайных чисел можноиспользовать как метод Math.random(), так иДля работы со строками используются классыSystem.String, представляющий неизменяемыестроки, и System.Text.StringBuilder,представляющий изменяемые строки.Обертками примитивных типов C# служатследующие структурные типы из пространстваимен System.Boolean, Byte, SByte, Int16, Int32, Int64,UInt16, UInt32, UInt64, Single, Double,Decimal.Они также содержат аналогичные константы иметоды.Для работы с форматированным строковымпредставлением чисел используются методыParse() и ToString() тех же классов сдополнительными параметрами, реализующимиинтерфейс IFormatProvider.