Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OSISP Part 3.DOC
Скачиваний:
42
Добавлен:
11.05.2015
Размер:
360.45 Кб
Скачать
  1. Мониторы в среде .Net. Ожидание выполнения условий с помощью методов Wait и Pulse.

Как и lock, мониторы не допускают одновременное выполнение несколькими потоками одних и тех же блоков кода. Метод Enter позволяет только одному методу переходить к последующим операторам, все прочие методы заблокированы, пока выполняемый метод не вызовет Exit. Это аналогично использованию ключевого слова lock. Ключевое слово lock реализовано с классом Monitor.

Рекомендуется использовать ключевое слово lock, а не класс Monitor, поскольку lock компактнее и потому что lock обеспечивает высвобождение монитора, даже если защищенный код создал исключение. Для этого применяется ключевое слово finally, которые выполняет свой блок кода вне зависимости от наличия исключений.

Класс Monitor контролирует доступ к объектам, предоставляя блокировку объекта одному потоку. Блокировки объектов предоставляют возможность ограничения доступа к части кода, обычно называемой критической секцией. Пока поток владеет блокировкой для объекта, никакой другой поток не может ею завладеть. Можно также использовать Monitor для того, чтобы убедиться, что ни один поток не имеет доступа к секции кода приложения, выполняющейся владельцем блокировки, пока другой поток не будет выполнять код, используя другой объект с блокировкой.

Monitor имеет следующие свойства:

Связывается с объектом по требованию.

Он несвязан, что означает, что он может быть вызван непосредственно из любого контекста.

Невозможно создать экземпляр класса Monitor.

Следующая информация хранится для каждого синхронизированного объекта:

Ссылка на поток, который в данный момент владеет блокировкой.

Ссылка на очередь готовности, которая содержит потоки, готовые получить блокировку.

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

Wait

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

Pulse(сигнал),PulseAll

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

  1. Асинхронный вызов делегатов.

Делегат можно вызвать на выполнение либо синхронно, как во всех приведенных ранее примерах, либо асинхронно с помощью методов BeginInvoke и EndInvoke. При вызове делегата с помощью метода BeginInvoke среда выполнения создает для исполнения метода отдельный поток и возвращает управление оператору, следующему за вызовом. При этом в исходном потоке можно продолжать вычисления.

Если при вызове BegiInvoke был указан метод обратного вызова, этот метод вызывается после завершения потока. Метод обратного вызова также задается с помощью делегата, при этом используется стандартный делегат AsyncCallback. В методе, обратного вызова для получения возвращаемого значения и выходных параметров применяется метод EndInvoke.

Если метод обратного вызова не был указан в параметрах метода BegiInvoke, метод EndInvoke можно использовать в потоке, инициировавшем запрос.

Класс Factorizer содержит метод Factorize, выполняющий разложение на множители. Этот метод асинхронно вызывается двумя способами: в методе Numl метод обратного вызова задается в BeginInvoke, в методе Num2 имеют место ожидание завершения потока и непосредственный вызов EndInvoke.

  1. Средства обобщенного (generic) программирования в языках C++ и C#.

Общие (или параметризованные) типы (generics) позволяют при описании классов, структур, методов и интерфейсов использовать параметризованные параметры (не указывать тип параметра в момент написания кода). Тип параметра определяется в момент объявления переменной соответствующего типа. Таким образом, можно создать некоторый общий элемент, тип который можно использовать в дальнейшем для данных различных типов. Программисты на C++ могут углядеть с общих типах сходство с шаблонами (templates), в чем-то эта аналогия будет верна.

Какие же преимущества дает использование общих типов?

Наиболее очевидное - повторное использование кода. Нет необходимости создавать два идентичных класса, отличающихся только типами параметров, достаточно создать один с параметризованными типами. При этом использование параметризованных типов позволяет создавать единый программный код для работы с различными типами данных. Например, единожды написанный алгоритм может работать и с целыми числами и с числами с плавающей десятичной точкой, при этом, не производя на каждом шаге проверку/приведение типа. Так Generics вытесняют классы объявленные с использованием типа object.

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

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

К сожалению, опытных программистов на C++ я должен несколько расстроить. Общие типы все-таки не соответствуют шаблонам в C++, поскольку параметризованные типы в C# не могут иметь типов по умолчанию. Параметризованные типы не могут быть использованы в качестве базовых классов для общих типов. Также в C# не допускается использования Generic классов в качестве параметров типов в других Generic классах.

Допускается применение шаблонов с целью реализации абстрактных алгоритмов, то есть шаблонов функций. template <class T> void sort(vector<T>& v); При вызове шаблонных функций компилятор подставляет тип данных и создает новый вариант функции. Если один и тот же тип данных используется несколько раз, то на все типы данных создается один шаблон функции. При использовании шаблонов существует три больших недостатка: * шаблоны невозможно отлаживать. Разработка шаблонов обычно ведется так: разрабатывается класс или функция конкретного типа данных; этот класс или функция параметризуются, то есть создается шаблон. * существенно замедляется время компиляции. В больших проектах оно может доходить до 30-60 минут. * очень быстро растут размеры объектных модулей и библиотек на диске. Компиляция относительно большого проекта в отладочном режиме может потребовать до 10 ГБ. Можно объявить несколько шаблонов функций с одним и тем же именем, а так же можно объявить комбинацию шаблонов и обычных функций с одинаковым именем. Шаблонные функции могут вызываться с явным указанием параметра шаблона: sqrt<int>(2); или без него: sqrt(2);

Как видно из примера, для того чтобы использовать общие типы нужно после объявления класса указать параметризованные типы: Generics<TYPE1, TYPE2> объявляет класс с двумя параметризованными типами. Более того, параметризованные типы могут быть использованы при объявлении делегатов функций.

Обобщения (generics) — еще один механизм, поддерживаемый общеязыковой исполняющей средой (CLR) и языками программирования, который является но­вой формой повторного использования кода, а именно повторным использова­нием алгоритма.

По сути, разработчик определяет алгоритм, например сортировку, поиск, за­мену, сравнение или преобразование, но не указывает типы данных, с которыми тот работает. Поэтому алгоритм может обобщенно применяться к объектам раз­ных типов. Используя готовый алгоритм, другой разработчик должен указать кон­кретные типы данных, например для алгоритма сортировки — Int32, String и т. д., а для алгоритма сравнения — DateTime, Versions...

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

В частности, в библиотеке FCL определен обобщенный алгоритм управления спис­ками, работающий с набором объектов. Тип объектов в обобщенном алгоритме не указан. Используя такой алгоритм, нужно указывать конкретные типы данных.

Защита исходного кода Разработчику, использующему обобщенный алго­ритм, не нужен доступ к исходному тексту алгоритма. А при работе с шабло­нами C++ или обобщениями Java разработчику нужен был исходный текст алгоритма.

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

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

Повышение производительности До появления обобщений одним из спо­собов определения обобщенного алгоритма было определение всех его чле­нов так, чтобы они по определению «умели» работать с типом данных Object. Чтобы этот алгоритм работал с экземплярами значимого типа, перед вызовом членов алгоритма CLR должна была упаковать этот экземпляр. Приве­дения типов также не нужны (см. предыдущий пункт), поэтому CLR не нужно проверять безопасность типов при их преобразовании, что также ускоряет работу кода.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]