Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OSISP Part 3.DOC
Скачиваний:
43
Добавлен:
11.05.2015
Размер:
360.45 Кб
Скачать
  1. Синхронизация программных потоков в среде .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.

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