Синхронизация данных для многопоточностиSynchronizing data for multithreading

Если несколько потоков могут вызывать свойства и методы отдельного объекта, эти вызовы важно синхронизировать.When multiple threads can make calls to the properties and methods of a single object, it is critical that those calls be synchronized. В противном случае поток может прерваться действиями другого потока, а объект может остаться в недопустимом состоянии.Otherwise one thread might interrupt what another thread is doing, and the object could be left in an invalid state. Класс, члены которого защищены от подобных прерываний, называется потокобезопасным.A class whose members are protected from such interruptions is called thread-safe.

.NET предоставляет несколько способов синхронизации доступа к экземпляру и статическим членам:.NET provides several strategies to synchronize access to instance and static members:

  • Синхронизированные области кода.Synchronized code regions. Используя класс Monitor или поддержку компилятора для этого класса, можно синхронизировать только тот блок кода, которому эту требуется, повысив тем самым производительность.You can use the Monitor class or compiler support for this class to synchronize only the code block that needs it, improving performance.

  • Синхронизация вручную.Manual synchronization. Вы можете использовать объекты синхронизации, предоставляемые библиотекой классов .NET.You can use the synchronization objects provided by the .NET class library. См. статью Обзор примитивов синхронизации, в которой обсуждается класс Monitor.See Overview of Synchronization Primitives, which includes a discussion of the Monitor class.

  • Синхронизированные контексты.Synchronized contexts. Для приложений .NET Framework и Xamarin вы можете использовать SynchronizationAttribute для реализации простой автоматической синхронизации объектов ContextBoundObject.For .NET Framework and Xamarin applications only, you can use the SynchronizationAttribute to enable simple, automatic synchronization for ContextBoundObject objects.

  • Классы коллекции в пространстве имен System.Collections.Concurrent.Collection classes in the System.Collections.Concurrent namespace. Эти классы предоставляют встроенные синхронизированные операции добавления и удаления.These classes provide built-in synchronized add and remove operations. Дополнительные сведения см. в разделе Потокобезопасные коллекции.For more information, see Thread-Safe Collections.

CLR предоставляет потоковую модель, где классы делятся на ряд категорий, которые можно синхронизировать различными способами в зависимости от конкретных требований.The common language runtime provides a thread model in which classes fall into a number of categories that can be synchronized in a variety of different ways depending on the requirements. В следующей таблице показано, какая поддержка синхронизации предоставляется для полей и методов в соответствующей категории синхронизации.The following table shows what synchronization support is provided for fields and methods with a given synchronization category.

КатегорияCategory Глобальные поляGlobal fields Статические поляStatic fields Статические методыStatic methods Поля экземпляраInstance fields Методы экземпляраInstance methods Определенные блоки кодаSpecific code blocks
Синхронизации нетNo Synchronization НетNo НетNo НетNo НетNo НетNo НетNo
Синхронизированные контекстыSynchronized Context НетNo НетNo НетNo ДаYes ДаYes НетNo
Синхронизированные области кодаSynchronized Code Regions НетNo НетNo Только если помеченыOnly if marked НетNo Только если помеченыOnly if marked Только если помеченыOnly if marked
Синхронизация вручнуюManual Synchronization ВручнуюManual ВручнуюManual ВручнуюManual ВручнуюManual ВручнуюManual ВручнуюManual

Синхронизации нетNo synchronization

По умолчанию для объектов.This is the default for objects. Любой поток может получить доступ к любому методу или полю в любое время.Any thread can access any method or field at any time. Одновременно обращаться к этим объектам может только один поток.Only one thread at a time should access these objects.

Синхронизация вручнуюManual synchronization

Библиотека классов .NET предоставляет ряд классов для синхронизации потоков.The .NET class library provides a number of classes for synchronizing threads. См. раздел Обзор примитивов синхронизации.See Overview of Synchronization Primitives.

Синхронизированные области кодаSynchronized code regions

Класс Monitor или ключевое слово компилятора можно использовать для синхронизации блоков кода, методов экземпляров и статических методов.You can use the Monitor class or a compiler keyword to synchronize blocks of code, instance methods, and static methods. Синхронизированные статические поля не поддерживаются.There is no support for synchronized static fields.

Visual Basic и C# поддерживают маркировку блоков кода ключевым словом определенного языка, оператором lock в C# или SyncLock в Visual Basic.Both Visual Basic and C# support the marking of blocks of code with a particular language keyword, the lock statement in C# or the SyncLock statement in Visual Basic. Если код выполняется потоком, он пытается получить блокировку.When the code is executed by a thread, an attempt is made to acquire the lock. Если блокировка уже получена другим потоком, поток блокируется, пока блокировка не станет доступной.If the lock has already been acquired by another thread, the thread blocks until the lock becomes available. Когда поток выходит из синхронизированного блока кода, блокировка снимается независимо от того, каким образом поток выходит из блока.When the thread exits the synchronized block of code, the lock is released, no matter how the thread exits the block.

Примечание

Инструкции lock И SyncLock реализуются с помощью Monitor.Enter и Monitor.Exit, чтобы в синхронизованной области с ними можно было использовать другие методы Monitor.The lock and SyncLock statements are implemented using Monitor.Enter and Monitor.Exit, so other methods of Monitor can be used in conjunction with them within the synchronized region.

Метод можно также оформить с помощью MethodImplAttribute со значением MethodImplOptions.Synchronized, который действует точно так же, как Monitor или одно из ключевых слов компилятора, блокируя все тело метода.You can also decorate a method with a MethodImplAttribute with a value of MethodImplOptions.Synchronized, which has the same effect as using Monitor or one of the compiler keywords to lock the entire body of the method.

С помощью Thread.Interrupt можно вывести поток из операций блокировки, таких как ожидание доступа к синхронизированной области кода.Thread.Interrupt can be used to break a thread out of blocking operations such as waiting for access to a synchronized region of code. Thread.Interrupt также используется для вывода потоков из таких операций, как Thread.Sleep.Thread.Interrupt is also used to break threads out of operations like Thread.Sleep.

Важно!

Не блокируйте тип, т. е. typeof(MyType) в C#, GetType(MyType) в Visual Basic или MyType::typeid в C++, для защиты методов static (методы Shared в Visual Basic).Do not lock the type — that is, typeof(MyType) in C#, GetType(MyType) in Visual Basic, or MyType::typeid in C++ — in order to protect static methods (Shared methods in Visual Basic). Вместо этого используйте закрытый статический объект.Use a private static object instead. Кроме того, не блокируйте методы экземпляра, используя this в C# (Me в Visual Basic).Similarly, do not use this in C# (Me in Visual Basic) to lock instance methods. Вместо этого используйте закрытый объект.Use a private object instead. Класс или экземпляр может заблокировать чужой код, вызвав при этом взаимоблокировку или проблемы производительности.A class or instance can be locked by code other than your own, potentially causing deadlocks or performance problems.

Поддержка компилятораCompiler support

Visual Basic и C# поддерживают ключевое слово языка для блокировки объекта с помощью Monitor.Enter и Monitor.Exit.Both Visual Basic and C# support a language keyword that uses Monitor.Enter and Monitor.Exit to lock the object. Visual Basic поддерживает оператор SyncLock, а C# поддерживает оператор lock.Visual Basic supports the SyncLock statement; C# supports the lock statement.

В обоих случаях, если в коде блока возникает исключение, блокировка, введенная оператором lock или SyncLock, автоматически снимается.In both cases, if an exception is thrown in the code block, the lock acquired by the lock or SyncLock is released automatically. Компиляторы C# и Visual Basic выдают блок try/finally с Monitor.Enter в начале оператора try и Monitor.Exit в блоке finally.The C# and Visual Basic compilers emit a try/finally block with Monitor.Enter at the beginning of the try, and Monitor.Exit in the finally block. Если исключение возникает в блоке lock или SyncLock, запускается обработчик finally, позволяющий выполнить очистку.If an exception is thrown inside the lock or SyncLock block, the finally handler runs to allow you to do any clean-up work.

Синхронизированные контекстыSynchronized Context

Только в приложениях .NET Framework и Xamarin можно использовать SynchronizationAttribute на любом ContextBoundObject для синхронизации всех методов и полей экземпляра.In .NET Framework and Xamarin applications only, you can use the SynchronizationAttribute on any ContextBoundObject to synchronize all instance methods and fields. Блокировка распространяется на все объекты с одним и тем же контекстным доменом.All objects in the same context domain share the same lock. К методам и полям могут обращаться сразу несколько потоков, но только по одному за раз.Multiple threads are allowed to access the methods and fields, but only a single thread is allowed at any one time.

См. такжеSee also