Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Cuando varios subprocesos pueden realizar llamadas a las propiedades y métodos de un solo objeto, es fundamental que esas llamadas se sincronicen. De lo contrario, un subproceso podría interrumpir lo que hace otro subproceso y el objeto podría dejarse en un estado no válido. La clase cuyos miembros están protegidos de tales interrupciones se conoce como segura para subprocesos.
.NET proporciona varias estrategias para sincronizar el acceso a los miembros estáticos y de instancia:
Regiones de código sincronizadas. Puede usar la clase Monitor o el soporte del compilador para esta clase para sincronizar únicamente el bloque de código que lo necesita, lo que mejora el rendimiento.
Sincronización manual. Puede usar los objetos de sincronización proporcionados por la biblioteca de clases .NET. Consulte Introducción a los primitivos de sincronización, que incluye una explicación de la Monitor clase .
Contextos sincronizados. Solo para las aplicaciones de .NET Framework, puede usar SynchronizationAttribute para habilitar la sincronización sencilla y automática de ContextBoundObject objetos.
Clases de colección en el espacio de nombres System.Collections.Concurrent. Estas clases proporcionan operaciones de adición y eliminación sincronizadas integradas. Para obtener más información, consulte Thread-Safe Colecciones.
Common Language Runtime proporciona un modelo de subproceso en el que las clases se dividen en una serie de categorías que se pueden sincronizar de varias maneras diferentes en función de los requisitos. En la tabla siguiente se muestra qué compatibilidad de sincronización se proporciona para campos y métodos con una categoría de sincronización determinada.
| Category | Campos globales | Campos estáticos | Métodos estáticos | Campos de instancia | Métodos de instancia | Bloques de código específicos |
|---|---|---|---|---|---|---|
| Sin sincronización | No | No | No | No | No | No |
| Contexto sincronizado | No | No | No | Yes | Yes | No |
| Regiones de código sincronizadas | No | No | Solo si está marcado | No | Solo si está marcado | Solo si está marcado |
| Sincronización manual | Manual | Manual | Manual | Manual | Manual | Manual |
Sin sincronización
Este es el valor predeterminado para los objetos . Cualquier subproceso puede acceder a cualquier método o campo en cualquier momento. Solo un subproceso a la vez debe tener acceso a estos objetos.
Sincronización manual
La biblioteca de clases .NET proporciona una serie de clases para sincronizar subprocesos. Consulte Introducción a los primitivos de sincronización.
Regiones de código sincronizadas
Puede usar la Monitor clase o una palabra clave del compilador para sincronizar bloques de código, métodos de instancia y métodos estáticos. No se admiten campos estáticos sincronizados.
Tanto Visual Basic como C# admiten el marcado de bloques de código con una palabra clave de lenguaje determinada, la lock instrucción en C# o la SyncLock instrucción en Visual Basic. Cuando se ejecuta el código en un subproceso, se realiza un intento de adquirir el bloqueo. Si otro subproceso ya lo ha adquirido, el subproceso se bloquea hasta que el bloqueo vuelva a estar disponible. Cuando el subproceso sale del bloque sincronizado de código, se libera el bloqueo, independientemente de cómo salga el subproceso del bloque.
Note
En .NET 9 y C# 13 o una versión posterior, si el destino lock es una instancia System.Threading.Lock dedicada, la instrucción lock usa Lock.EnterScope() para crear una región sincronizada.
Visual Basic no admite System.Threading.Lock en SyncLock, por lo tanto, siga usando SyncLock con un tipo de referencia privado dedicado.
Si el lock objetivo no es una instancia de Lock, entonces, para cualquier uso de SyncLock, el compilador usa Monitor.Enter y Monitor.Exit. Debido a esa implementación, todavía puede usar otros Monitor métodos en la región sincronizada.
También puede decorar un método con MethodImplAttribute con un valor de MethodImplOptions.Synchronized, lo que tiene el mismo efecto que usar Monitor o una de las palabras clave del compilador para bloquear todo el cuerpo del método.
Thread.Interrupt se puede usar para interrumpir un subproceso de operaciones de bloqueo, como esperar el acceso a una región sincronizada del código. Thread.Interrupt también se usa para interrumpir subprocesos de operaciones como Thread.Sleep.
Importante
No bloquee el tipo ( es decir, typeof(MyType) en C#, GetType(MyType) en Visual Basic o MyType::typeid en C++) para proteger static métodos (Shared métodos en Visual Basic). Use un objeto estático privado en su lugar. Del mismo modo, no use this en C# (Me en Visual Basic) para bloquear métodos de instancia. Use un objeto privado en su lugar. Una clase o instancia se puede bloquear mediante código distinto del suyo propio, lo que podría provocar interbloqueos o problemas de rendimiento.
Compatibilidad con el compilador
Tanto Visual Basic como C# admiten una palabra clave de lenguaje que usa Monitor.Enter y Monitor.Exit para bloquear el objeto. Visual Basic admite la instrucción SyncLock; C# admite la instrucción lock.
En ambos casos, si se produce una excepción en el bloque de código, el bloqueo adquirido mediante lock o SyncLock se libera automáticamente. Los compiladores de C# y Visual Basic emiten un bloque try/finally con Monitor.Enter al principio del intento y Monitor.Exit en el bloque finally. Si se produce una excepción dentro del bloque lock o SyncLock, el controlador finally se ejecuta para que pueda realizar cualquier tarea de limpieza.
Contexto sincronizado
Solo en aplicaciones de .NET Framework, puede usar SynchronizationAttribute en cualquier ContextBoundObject para sincronizar todos los métodos y campos de instancia. Todos los objetos del mismo dominio de contexto comparten el mismo bloqueo. Se permiten varios subprocesos para acceder a los métodos y campos, pero solo se permite un único subproceso en cualquier momento.