Lock Clase
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Nota
Para usar esta API en versión preliminar, debe habilitar las características en versión preliminar en su proyecto estableciendo la propiedad EnablePreviewFeatures
en True
en el archivo del proyecto. Para más información, vea https://aka.ms/dotnet-preview-features.
Proporciona un mecanismo para lograr la exclusión mutua en regiones de código entre diferentes subprocesos.
public ref class Lock sealed
[System.Runtime.Versioning.RequiresPreviewFeatures]
public sealed class Lock
[<System.Runtime.Versioning.RequiresPreviewFeatures>]
type Lock = class
Public NotInheritable Class Lock
- Herencia
-
Lock
- Atributos
Comentarios
La Lock clase se puede usar para definir regiones de código que requieren acceso mutuamente excluyente entre subprocesos de un proceso, denominados secciones críticas, para evitar accesos simultáneos a un recurso. Se Lock
puede especificar y salir, donde la región de código entre la entrada y la salida es una sección crítica asociada al bloqueo. Se dice que un subproceso que entra en un bloqueo contiene o posee el bloqueo hasta que sale del bloqueo. Como máximo, un subproceso puede contener un bloqueo en un momento dado. Un subproceso puede contener varios bloqueos. Un subproceso puede escribir un bloqueo varias veces antes de salir de él, como de forma recursiva. Un subproceso que no puede entrar en un bloqueo inmediatamente puede esperar hasta que se pueda especificar el bloqueo o hasta que expire un tiempo de espera especificado.
Al usar los Enter métodos o TryEnter para escribir un bloqueo:
- Asegúrese de que el subproceso sale del bloqueo con Exit incluso en caso de excepciones, como en C# mediante un
try/finally
bloque . - Cuando se introduzca y salga del bloqueo en un método de C#
async
, asegúrese de que no haya entreawait
entrar y salir. Los subprocesos mantienen bloqueos y el código siguienteawait
podría ejecutarse en otro subproceso.
Se recomienda usar el EnterScope método con una construcción de lenguaje que elimine automáticamente el devuelto Lock.Scope , como la palabra clave de C# using
, o para usar la palabra clave de C# lock
, ya que garantizan que el bloqueo se salga en casos excepcionales. Estos patrones también pueden tener ventajas de rendimiento sobre el uso Enter/TryEnter
de y Exit
. En el fragmento de código siguiente se muestran varios patrones para entrar y salir de un bloqueo.
public sealed class ExampleDataStructure
{
private readonly Lock _lockObj = new();
public void Modify()
{
lock (_lockObj)
{
// Critical section associated with _lockObj
}
using (_lockObj.EnterScope())
{
// Critical section associated with _lockObj
}
_lockObj.Enter();
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
if (_lockObj.TryEnter())
{
try
{
// Critical section associated with _lockObj
}
finally { _lockObj.Exit(); }
}
}
}
Al usar la palabra clave de C# lock
o similar a entrar y salir de un bloqueo, el tipo de la expresión debe ser precisamente System.Threading.Lock
. Si el tipo de la expresión es cualquier otra cosa, como Object
o un tipo genérico como T
, se puede usar una implementación diferente que no sea intercambiable en su lugar (como Monitor). Para obtener más información, consulte el speclet del compilador pertinente.
Interrupt puede interrumpir los subprocesos que están esperando entrar en un bloqueo. En los subprocesos STA de Windows, espera a que los bloqueos permitan el bombeo de mensajes que pueden ejecutar otro código en el mismo subproceso durante una espera. Algunas características de las esperas se pueden invalidar mediante un personalizado SynchronizationContext.
Nota
Un subproceso que entra en un bloqueo, incluidas varias veces, como de forma recursiva, debe salir del bloqueo el mismo número de veces para salir completamente del bloqueo y permitir que otros subprocesos entren en el bloqueo. Si un subproceso sale mientras mantiene un Lock
, el comportamiento de Lock
se convierte en indefinido.
Precaución
Si, en una ruta de acceso de código, un subproceso podría entrar en varios bloqueos antes de salir de ellos, asegúrese de que todas las rutas de acceso de código que puedan escribir cualquiera de esos bloqueos en el mismo subproceso los introduzcan en el mismo orden. De lo contrario, podría provocar interbloqueos. Por ejemplo, tenga en cuenta que, en un subproceso de ruta T1
de acceso de código, entra en bloqueo L1
y, después, se bloquea L2
antes de salir y, en otro, el subproceso de ruta T2
de acceso de código entra en ambos bloqueos en el orden inverso. En ese escenario, sería posible que se produzca el siguiente orden de eventos: escribe , escribe , intenta entrar y esperas, T2
intenta entrar L2
L1
y esperar. T1
L2
T2
L1
T1
Hay un interbloqueo entre T1
y T2
que no se puede resolver, y cualquier otro subproceso que intente entrar en cualquiera de los bloqueos en el futuro también se bloqueará.
Constructores
Lock() |
Inicializa una nueva instancia de la clase Lock. |
Propiedades
IsHeldByCurrentThread |
Obtiene un valor que indica si el subproceso actual mantiene el bloqueo. |
Métodos
Enter() |
Entra en el bloqueo, esperando si es necesario hasta que se pueda introducir el bloqueo. |
EnterScope() |
Entra en el bloqueo, esperando si es necesario hasta que se pueda introducir el bloqueo. |
Equals(Object) |
Determina si el objeto especificado es igual que el objeto actual. (Heredado de Object) |
Exit() |
Sale del bloqueo. |
GetHashCode() |
Sirve como la función hash predeterminada. (Heredado de Object) |
GetType() |
Obtiene el Type de la instancia actual. (Heredado de Object) |
MemberwiseClone() |
Crea una copia superficial del Object actual. (Heredado de Object) |
ToString() |
Devuelve una cadena que representa el objeto actual. (Heredado de Object) |
TryEnter() |
Intenta entrar en el bloqueo sin esperar. |
TryEnter(Int32) |
Intenta entrar en el bloqueo, esperando si es necesario para el número especificado de milisegundos hasta que se pueda introducir el bloqueo. |
TryEnter(TimeSpan) |
Intenta entrar en el bloqueo, esperando si es necesario hasta que se pueda especificar el bloqueo o hasta que expire el tiempo de espera especificado. |