Sincronizar datos para subprocesamiento múltiple
Actualización: noviembre 2007
Cuando varios subprocesos pueden llamar a las propiedades y métodos de un solo objeto, es fundamental sincronizar las llamadas. En caso contrario, un subproceso puede interrumpir la ejecución de otro subproceso, y el objeto puede terminar teniendo un estado no válido. Se dice que una clase es segura para subprocesos cuando sus miembros están protegidos contra este tipo de interrupciones.
La infraestructura de Common Language proporciona diversas estrategias para sincronizar el acceso a instancias y miembros estáticos:
Regiones de código sincronizado. Puede utilizar la clase Monitor o la compatibilidad del compilador de esta clase para sincronizar sólo el bloque de código necesario y así mejorar el rendimiento.
Sincronización manual.Puede utilizar los objetos de sincronización proporcionados por la biblioteca de clases de .NET Framework. Vea Información general sobre los primitivos de sincronización, que incluye una discusión de la clase Monitor.
Contextos sincronizados. Puede utilizar SynchronizationAttribute para habilitar la sincronización automática y simple de objetos ContextBoundObject.
Propiedad Synchronized. Sólo algunas clases, como Hashtable y Queue, proporcionan una propiedad Synchronized que devuelve un contenedor seguro para subprocesos a una instancia de la clase. Vea Colecciones y sincronización (seguridad para subprocesos).
Common Language Runtime proporciona un modelo de subproceso en el que las clases pertenecen a un número de categorías que pueden sincronizarse de varias formas diferentes en función de los requisitos. En la tabla siguiente se muestra la compatibilidad de sincronización proporcionada para campos y métodos con una categoría de sincronización dada.
Categoría |
Campos globales |
Campos estáticos |
Métodos estáticos |
Campos de instancia |
Métodos de instancia |
Bloques de código específico |
---|---|---|---|---|---|---|
Sin sincronización |
No |
No |
No |
No |
No |
No |
Contexto sincronizado |
No |
No |
No |
Sí |
Sí |
No |
Regiones de código sincronizado |
No |
No |
Sólo si se marca |
No |
Sólo si se marca |
Sólo si se marca |
Sincronización manual |
Manual |
Manual |
Manual |
Manual |
Manual |
Manual |
Sin sincronización
Ésta es la opción predeterminada para objetos. Cualquier subproceso puede tener acceso a un método o campo en cualquier momento. Sólo debería tener acceso a estos objetos un subproceso cada vez.
Sincronización manual
La biblioteca de clases de .NET Framework proporciona una serie de clases para sincronizar los subprocesos. Vea Información general sobre los primitivos de sincronización.
Regiones de código sincronizado
Puede utilizar la clase Monitor o una palabra clave del compilador para sincronizar bloques de código, métodos de instancia y métodos estáticos. No se admiten los campos estáticos sincronizados.
Visual Basic y C# admiten el marcado de bloques de código con una determinada palabra clave de lenguaje, la instrucción lock en C# o la instrucción SyncLock en Visual Basic. Cuando un subproceso ejecuta el código, se realiza un intento de bloqueo. Si otro subproceso ha realizado ya el bloqueo, el subproceso se bloquea hasta que esté disponible el bloqueo. Cuando el subproceso sale del bloque sincronizado de código, el bloqueo se libera, independientemente de cómo salga del bloque el subproceso.
Nota: |
---|
Las instrucciones lock y SyncLock se implementan mediante Monitor.Enter y Monitor.Exit, por lo que se pueden utilizar otros métodos de Monitor con ellas en el área sincronizada. |
También puede decorar un método con MethodImplAttribute y MethodImplOptions.Synchronized, lo que tiene el mismo efecto que utilizar Monitor o una de las palabras clave del compilador para bloquear todo el cuerpo del método.
Se puede utilizar Thread.Interrupt para que un subproceso salga de operaciones de bloqueo, por ejemplo, de la espera para tener acceso a una región de código sincronizado. También se utiliza Thread.Interrupt para que los subprocesos salgan de operaciones como Thread.Sleep.
Nota importante: |
---|
No bloquee el tipo, es decir, typeof(MyType) en C#, GetType(MyType) en Visual Basic o MyType::typeid en C++, para proteger los métodos static (métodos Shared en Visual Basic). Utilice en su lugar un objeto estático privado. De igual forma, no utilice this en C# (Me en Visual Basic) para bloquear los métodos de instancia. Utilice en su lugar un objeto privado. Una clase o instancia se puede bloquear por código distinto del suyo propio, produciendo potenciales interbloqueos o problemas de rendimiento. |
Compatibilidad del compilador
Visual Basic y C# admiten una palabra clave que utiliza Monitor.Enter y Monitor.Exit para bloquear el objeto. Visual Basic admite la instrucción SyncLock y C# admite la instrucción lock.
En ambos casos, si se inicia una excepción en el bloque de código, el bloqueo adquirido por lock o SyncLock se libera automáticamente. Los compiladores de C# y de Visual Basic emiten un bloque try/finally con Monitor.Enter al principio de try y Monitor.Exit en el bloque finally. Si se inicia una excepción dentro del bloque lock o SyncLock, se ejecuta el controlador finally para permitir realizar cualquier trabajo de limpieza.
Contexto sincronizado
Puede utilizar el atributo SynchronizationAttribute en cualquier objeto ContextBoundObject para sincronizar todos los métodos y campos de instancia. Todos los objetos del mismo dominio de contexto comparten el mismo bloqueo. Varios subprocesos pueden tener acceso a los métodos y campos, pero sólo uno al mismo tiempo.
Vea también
Conceptos
Subprocesos y subprocesamiento
Información general sobre los primitivos de sincronización