
- •Сравнительная характеристика технологий .Net и Java.
- •Промежуточный язык il и байт-код Java. Сравнительная характеристика.
- •Основные принципы построения архитектуры .Net.
- •Сборки (assembly) в среде .Net. Проблема версионности сборок и ее решение.
- •Общая система типов данных в среде .Net. Размерные и ссылочные типы данных.
- •Модель автоматической утилизации динамической памяти, основанная на сборке мусора. Проблема недетерминизма.
- •Модель автоматической утилизации динамической памяти, основанная на аппаратной поддержке (тегированной памяти).
- •Сборка мусора в среде .Net. Построение графа достижимых объектов.
- •Сборка мусора в среде .Net. Механизм поколений объектов.
- •Завершение объектов в среде .Net. Метод Finalize. Список завершаемых объектов (finalization queue) и очередь завершения (freachable queue).
- •Динамические массивы в среде. Net и языке c#.
- •События в среде .Net; реализация событий посредством делегатов.
- •Исключительные ситуации и реакция на них в среде .Net.
- •Средства многопоточного программирования в среде .Net. Автономные потоки. Пул потоков.
- •Асинхронные операции в среде .Net. Асинхронный вызов делегатов.
- •Синхронизация программных потоков в среде .Net. Блокировки.
- •Синхронизация программных потоков в среде .Net. Атомарные (Interlocked-) операции.
- •Мониторы в среде .Net. Ожидание выполнения условий с помощью методов Wait и Pulse.
- •Асинхронный вызов делегатов.
- •Итераторы в среде .Net. Создание и использование итераторов.
- •Атрибуты в среде .Net и языке c#. Создание своих атрибутов.
- •Сервисно-ориентированная архитектура (соа) и ее принципы.
- •Технология wcf. Создание сервиса и клиента.
- •Взаимодействие управляемого и неуправляемого кода в среде .Net на примере вызова функций Windows api.
-
Синхронизация программных потоков в среде .Net. Блокировки.
Чтобы предотвратить повреждение ресурса по причине одновременного доступа многих потоков, нужно использовать конструкции синхронизации потоков.
Многие из конструкций синхронизации потоков в CLR в действительности всего лишь объектно-ориентированные оболочки классов, построенные на базе конструкций синхронизации потоков Win32. В конце концов, потоки CLR — это потоки Windows, а это значит, что именно Windows планирует и контролирует их синхронизацию.
Для простых операций над числовыми типами данных синхронизация потоков выполняется с помощью членов класса Interlocked.
Методы этого класса защищены от ошибок, которые могут возникнуть при переключении контекстов планировщиком в то время, когда поток обновляет переменную, а она может быть доступна другим потокам, или когда выполняются одновременно два потока на различных процессорах. Члены этого класса не выдают исключения.
Методы Increment и Decrement увеличивают или уменьшают значение переменной и сохраняют результат в одной операции. На большинстве компьютеров увеличение значения переменной не является атомарной операцией, а требует следующих шагов:
Загрузить значение из переменной экземпляра в регистр.
Увеличить или уменьшить значение.
Сохранить значение в переменной экземпляра.
Если не использовать методы Increment и Decrement, поток может быть прерван после выполнения первых двух шагов. Затем другой поток может выполнить все три шага. Когда первый поток продолжит выполнение, он переписывает значение в переменную экземпляра, и эффект увеличения или уменьшения значения, выполненного вторым потоком, теряется.
Метод Exchange обменивает значения заданных переменных на уровне атомарных операций. Метод CompareExchange сочетает в себе две операции: сравнивание двух значений и сохранение третьего значения в одной из переменных, которое зависит от результата сравнения. Операции сравнения и обмена выполняются как атомарные.
Ключевое слово lock используется для того, чтобы выполнение блока кода не прерывалось кодом, выполняемым в других потоках. Для этого нужно получить взаимоисключающую блокировку для данного объекта на время длительности блока кода.
Оператор lock начинается с ключевого слова lock, которому в качестве аргумента указывается объект, и за которым следует блок кода, который должен выполняться одновременно только в одном потоке.
Аргумент, предоставляемый ключевому слову lock, должен быть объектом на основе ссылочного типа; он используется для определения области блокировки.
Строго говоря, объект, предоставляемый для lock, используется только для того, чтобы уникальным образом определить ресурс, к которому предоставляется доступ для различных потоков, поэтому это может быть произвольный экземпляр класса. В действительности этот объект обычно представляет ресурс, для которого требуется синхронизация потоков. Например, если объект контейнера должен использоваться в нескольких потоках, то контейнер можно передать блокировке, а блок синхронизированного кода после блокировки должен получить доступ к контейнеру. Если другие потоки блокируются для того же контейнера перед доступом к нему, обеспечивается безопасная синхронизация доступа к объекту.
Как правило, рекомендуется избегать блокировки типа public или экземпляров объектов, которыми не управляет код вашего приложения. Например, использование lock(this) может привести к неполадкам, если к экземпляру разрешен открытый доступ, поскольку внешний код также может блокировать объект. Это может привести к созданию ситуаций взаимной блокировки, когда два или несколько потоков будут ожидать высвобождения одного и того же объекта. По этой же причине блокировка открытого типа данных (в отличие от объектов) может привести к неполадкам. Блокировка строковых литералов наиболее опасна, поскольку строковые литералы интернируются средой CLR. Это означает, что если во всей программе есть один экземпляр любого строкового литерала, точно такой же объект будет представлять литерал во всех запущенных доменах приложения и во всех потоках. В результате блокировка, включенная для строки с одинаковым содержимым во всем приложении, блокирует все экземпляры этой строки в приложении. По этой причине лучше использовать блокировку закрытых или защищенных членов, для которых интернирование не применяется. В некоторых классах есть члены, специально предназначенные для блокировки. Например, в типе Array есть SyncRoot. Во многих типах коллекций есть член SyncRoot.