Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Если несколько потоков могут вызывать свойства и методы одного объекта, важно синхронизировать эти вызовы. В противном случае один поток может прервать выполнение другого потока, и объект может быть оставлен в недопустимом состоянии. Класс, элементы которого защищены от таких прерываний, называют потокобезопасным.
.NET предоставляет несколько стратегий синхронизации доступа к экземпляру и статическим элементам:
Синхронизированные области кода. Вы можете использовать Monitor поддержку класса или компилятора для этого класса, чтобы синхронизировать только блок кода, необходимый для него, повышая производительность.
Синхронизация вручную. Вы можете использовать объекты синхронизации, предоставляемые библиотекой классов .NET. См. Обзор примитивов синхронизации, который включает обсуждение класса Monitor.
Синхронизированные контексты. Только для приложений .NET Framework можно использовать SynchronizationAttribute, чтобы включить простую автоматическую синхронизацию для объектов ContextBoundObject.
Классы коллекций в пространстве имён System.Collections.Concurrent. Эти классы предоставляют встроенные синхронизированные операции добавления и удаления. Дополнительные сведения см. в разделе Thread-Safe Коллекции.
Среда CLR предоставляет модель потока, в которой классы делятся на ряд категорий, которые можно синхронизировать различными способами в зависимости от требований. В следующей таблице показано, какая поддержка синхронизации предоставляется для полей и методов с заданной категорией синхронизации.
| Category | Глобальные поля | Статические поля | Статические методы | Поля экземпляра | Методы экземпляра | Определенные блоки кода |
|---|---|---|---|---|---|---|
| Синхронизация не выполняется | Нет | Нет | Нет | Нет | Нет | Нет |
| Синхронизированный контекст | Нет | Нет | Нет | Yes | Yes | Нет |
| Синхронизированные регионы кода | Нет | Нет | Только в том случае, если отмечено | Нет | Только в том случае, если отмечено | Только в том случае, если отмечено |
| Синхронизация вручную | Руководство | Руководство | Руководство | Руководство | Руководство | Руководство |
Без синхронизации
Это значение по умолчанию для объектов. Любой поток может получить доступ к любому методу или полю в любое время. Доступ к этим объектам должен получить только один поток за раз.
Ручная синхронизация
Библиотека классов .NET предоставляет ряд классов для синхронизации потоков. См. Обзор примитивов синхронизации.
Синхронизированные области кода
Класс или ключевое Monitor слово компилятора можно использовать для синхронизации блоков кода, методов экземпляра и статических методов. Не поддерживается синхронизированные статические поля.
Как Visual Basic, так и C# поддерживают маркировку блоков кода с определенным ключевым словом языка, lock оператором в C# или SyncLock инструкцией в Visual Basic. При выполнении кода потоком предпринимается попытка получить блокировку. Если блокировка уже захвачена другим потоком, поток блокируется до тех пор, пока блокировка не освободится. Когда поток выходит из синхронизированного блока кода, блокировка освобождается независимо от того, как поток выходит из блока.
Замечание
В .NET 9 и C# 13 или более поздних версиях, если целевой объект lock является отдельным экземпляром System.Threading.Lock, инструкция lock использует Lock.EnterScope(), чтобы создать синхронизированную область.
Visual Basic не поддерживает System.Threading.Lock в SyncLock, поэтому продолжайте использовать SyncLock с выделенным закрытым ссылочным типом.
Если объект lock назначения не является экземпляром Lock, то во всех случаях использования SyncLock компилятор использует Monitor.Enter и Monitor.Exit. Из-за этой реализации можно по-прежнему использовать другие Monitor методы в синхронизированном регионе.
Метод также можно пометить атрибутом MethodImplAttribute со значением MethodImplOptions.Synchronized, что эквивалентно использованию Monitor или одного из ключевых слов компилятора для блокировки всего тела метода.
Thread.Interrupt можно использовать для разрыва потока из блокирующих операций, таких как ожидание доступа к синхронизированному региону кода. Thread.Interrupt также используется для прерывания потоков из таких операций, как Thread.Sleep.
Important
Не блокируйте тип (например, typeof(MyType) в C#, GetType(MyType) в Visual Basic или MyType::typeid В C++), чтобы защитить static методы (Sharedметоды в Visual Basic). Вместо этого используйте частный статический объект. Аналогичным образом не используйте this в C# (Meв Visual Basic) для блокировки методов экземпляра. Вместо этого используйте частный объект. Класс или экземпляр можно заблокировать по коду, отличному от собственного, что может привести к взаимоблокировкам или проблемам с производительностью.
Поддержка компилятора
И Visual Basic, и C# поддерживают ключевое слово языка, использующее Monitor.Enter и Monitor.Exit для блокировки объекта. Visual Basic поддерживает инструкцию SyncLock; C# поддерживает инструкцию блокировки.
В обоих случаях, если в блоке кода возникает исключение, блокировка, установленная с помощью lock или SyncLock, освобождается автоматически. Компиляторы C# и Visual Basic генерируют блок try/finally с Monitor.Enter в начале блока try и Monitor.Exit в блоке finally. Если исключение выбрасывается внутри блока lock или SyncLock, выполняется обработчик finally, позволяя выполнить все необходимые действия по очистке.
Синхронизированный контекст
Только в приложениях .NET Framework можно использовать SynchronizationAttribute в любом ContextBoundObject для синхронизации всех методов экземпляра и полей. Все объекты в одном домене контекста используют одну блокировку. Доступ к методам и полям разрешен для нескольких потоков, но только один поток разрешен в любое время.