# SpinLock Estructura

## Definición

Proporciona una primitiva de bloqueo de exclusión mutua donde un subproceso que intenta adquirir el bloqueo espera en un bucle repetidamente comprobando hasta que haya un bloqueo disponible.Provides a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop repeatedly checking until the lock becomes available.

``public value class SpinLock``
``````[System.Runtime.InteropServices.ComVisible(false)]
public struct SpinLock``````
``type SpinLock = struct``
``Public Structure SpinLock``
Herencia
SpinLock
Atributos

## Ejemplos

En el ejemplo siguiente se muestra cómo usar SpinLockun:The following example shows how to use a SpinLock:

``````using System;
using System.Linq;
using System.Text;

class SpinLockDemo
{

// Demonstrates:
//      Default SpinLock construction ()
//      SpinLock.Enter(ref bool)
//      SpinLock.Exit()
static void SpinLockSample1()
{
SpinLock sl = new SpinLock();

StringBuilder sb = new StringBuilder();

// Action taken by each parallel job.
// Append to the StringBuilder 10000 times, protecting
Action action = () =>
{
bool gotLock = false;
for (int i = 0; i < 10000; i++)
{
gotLock = false;
try
{
sl.Enter(ref gotLock);
sb.Append((i % 10).ToString());
}
finally
{
// Only give up the lock if you actually acquired it
if (gotLock) sl.Exit();
}
}
};

// Invoke 3 concurrent instances of the action above
Parallel.Invoke(action, action, action);

// Check/Show the results
Console.WriteLine("sb.Length = {0} (should be 30000)", sb.Length);
Console.WriteLine("number of occurrences of '5' in sb: {0} (should be 3000)",
sb.ToString().Where(c => (c == '5')).Count());
}

// Demonstrates:
//      Default SpinLock constructor (tracking thread owner)
//      SpinLock.Enter(ref bool)
//      SpinLock.Exit() throwing exception
//      SpinLock.IsHeld
static void SpinLockSample2()
{
// Instantiate a SpinLock
SpinLock sl = new SpinLock();

// These MRESs help to sequence the two jobs below
ManualResetEventSlim mre1 = new ManualResetEventSlim(false);
ManualResetEventSlim mre2 = new ManualResetEventSlim(false);
bool lockTaken = false;

{
try
{
sl.Enter(ref lockTaken);
mre1.Set(); // Signal Task B to commence with its logic

// Wait for Task B to complete its logic
// (Normally, you would not want to perform such a potentially
// heavyweight operation while holding a SpinLock, but we do it
// here to more effectively show off SpinLock properties in
mre2.Wait();
}
finally
{
if (lockTaken) sl.Exit();
}
});

{
mre1.Wait(); // wait for Task A to signal me
Console.WriteLine("Task B: sl.IsHeld = {0} (should be true)", sl.IsHeld);

try
{
sl.Exit();
Console.WriteLine("Task B: Released sl, should not have been able to!");
}
catch (Exception e)
{
Console.WriteLine("Task B: sl.Exit resulted in exception, as expected: {0}", e.Message);
}

mre2.Set(); // Signal Task A to exit the SpinLock
});

// Wait for task completion and clean up
mre1.Dispose();
mre2.Dispose();
}

// Demonstrates:
//      SpinLock constructor(false) -- thread ownership not tracked
static void SpinLockSample3()
{
// Create SpinLock that does not track ownership/threadIDs
SpinLock sl = new SpinLock(false);

// Used to synchronize with the Task below
ManualResetEventSlim mres = new ManualResetEventSlim(false);

// We will verify that the Task below runs on a separate thread

// Now enter the SpinLock.  Ordinarily, you would not want to spend so
// much time holding a SpinLock, but we do it here for the purpose of
// demonstrating that a non-ownership-tracking SpinLock can be exited
// by a different thread than that which was used to enter it.
bool lockTaken = false;
sl.Enter(ref lockTaken);

// Create a separate Task from which to Exit() the SpinLock
{

// Now exit the SpinLock
try
{
sl.Exit();
Console.WriteLine("worker task: successfully exited SpinLock, as expected");
}
catch (Exception e)
{
Console.WriteLine("worker task: unexpected failure in exiting SpinLock: {0}", e.Message);
}

// Notify main thread to continue
mres.Set();
});

// Do this instead of worker.Wait(), because worker.Wait() could inline the worker Task,
// causing it to be run on the same thread.  The purpose of this example is to show that
mres.Wait();

// now Wait() on worker and clean up
worker.Wait();
mres.Dispose();
}

}
``````
``````Imports System.Text

Module SpinLockDemo

' Demonstrates:
' Default SpinLock construction ()
' SpinLock.Enter(ref bool)
' SpinLock.Exit()
Private Sub SpinLockSample1()
Dim sl As New SpinLock()

Dim sb As New StringBuilder()

' Action taken by each parallel job.
' Append to the StringBuilder 10000 times, protecting
Dim action As Action =
Sub()
Dim gotLock As Boolean = False
For i As Integer = 0 To 9999
gotLock = False
Try
sl.Enter(gotLock)
sb.Append((i Mod 10).ToString())
Finally
' Only give up the lock if you actually acquired it
If gotLock Then
sl.[Exit]()
End If
End Try
Next
End Sub

' Invoke 3 concurrent instances of the action above
Parallel.Invoke(action, action, action)

' Check/Show the results
Console.WriteLine("sb.Length = {0} (should be 30000)", sb.Length)
Console.WriteLine("number of occurrences of '5' in sb: {0} (should be 3000)", sb.ToString().Where(Function(c) (c = "5"c)).Count())
End Sub

' Demonstrates:
' Default SpinLock constructor (tracking thread owner)
' SpinLock.Enter(ref bool)
' SpinLock.Exit() throwing exception
' SpinLock.IsHeld
Private Sub SpinLockSample2()
' Instantiate a SpinLock
Dim sl As New SpinLock()

' These MRESs help to sequence the two jobs below
Dim mre1 As New ManualResetEventSlim(False)
Dim mre2 As New ManualResetEventSlim(False)
Dim lockTaken As Boolean = False

Sub()
Try
sl.Enter(lockTaken)
mre1.[Set]()
' Signal Task B to commence with its logic
' Wait for Task B to complete its logic
' (Normally, you would not want to perform such a potentially
' heavyweight operation while holding a SpinLock, but we do it
' here to more effectively show off SpinLock properties in
mre2.Wait()
Finally
If lockTaken Then
sl.[Exit]()
End If
End Try
End Sub)

Sub()
mre1.Wait()
' wait for Task A to signal me
Console.WriteLine("Task B: sl.IsHeld = {0} (should be true)", sl.IsHeld)

Try
sl.[Exit]()
Console.WriteLine("Task B: Released sl, should not have been able to!")
Catch e As Exception
Console.WriteLine("Task B: sl.Exit resulted in exception, as expected: {0}", e.Message)
End Try

' Signal Task A to exit the SpinLock
mre2.[Set]()
End Sub)

' Wait for task completion and clean up
mre1.Dispose()
mre2.Dispose()
End Sub

' Demonstrates:
' SpinLock constructor(false) -- thread ownership not tracked
Private Sub SpinLockSample3()
' Create SpinLock that does not track ownership/threadIDs
Dim sl As New SpinLock(False)

' Used to synchronize with the Task below
Dim mres As New ManualResetEventSlim(False)

' We will verify that the Task below runs on a separate thread

' Now enter the SpinLock.  Ordinarily, you would not want to spend so
' much time holding a SpinLock, but we do it here for the purpose of
' demonstrating that a non-ownership-tracking SpinLock can be exited
' by a different thread than that which was used to enter it.
Dim lockTaken As Boolean = False
sl.Enter(lockTaken)

Sub()

' Now exit the SpinLock
Try
sl.[Exit]()
Console.WriteLine("worker task: successfully exited SpinLock, as expected")
Catch e As Exception
Console.WriteLine("worker task: unexpected failure in exiting SpinLock: {0}", e.Message)
End Try

' Notify main thread to continue
mres.[Set]()
End Sub)

' Do this instead of worker.Wait(), because worker.Wait() could inline the worker Task,
' causing it to be run on the same thread. The purpose of this example is to show that
mres.Wait()

' now Wait() on worker and clean up
worker.Wait()
mres.Dispose()
End Sub

End Module
``````

## Comentarios

Para obtener un ejemplo de cómo usar un bloqueo de bucle, consulte Cómo: Use SpinLock para la sincronizaciónde bajo nivel.For an example of how to use a Spin Lock, see How to: Use SpinLock for Low-Level Synchronization.

Los bloqueos de giro se pueden usar para los bloqueos de nivel de hoja en los Monitorque la asignación de objetos implicada mediante el uso de, en tamaño o debido a la presión de recolección de elementos no utilizados, es demasiado costosa.Spin locks can be used for leaf-level locks where the object allocation implied by using a Monitor, in size or due to garbage collection pressure, is overly expensive. Un bloqueo de giro puede ser útil para evitar el bloqueo; sin embargo, si espera una cantidad significativa de bloqueos, probablemente no use bloqueos de giro debido al giro excesivo.A spin lock can be useful to avoid blocking; however, if you expect a significant amount of blocking, you should probably not use spin locks due to excessive spinning. El giro puede ser beneficioso cuando los bloqueos son específicos y de gran número (por ejemplo, un bloqueo por nodo en una lista vinculada) y también cuando las horas de retención de bloqueo son siempre muy cortas.Spinning can be beneficial when locks are fine-grained and large in number (for example, a lock per node in a linked list) and also when lock hold-times are always extremely short. En general, mientras se mantiene un bloqueo de bucle, debe evitarse cualquiera de estas acciones:In general, while holding a spin lock, one should avoid any of these actions:

• medidablocking,

• llamar a todo lo que se puede bloquear,calling anything that itself may block,

• contener más de un bloque de número al mismo tiempo.holding more than one spin lock at once,

• realizar llamadas enviadas dinámicamente (interfaz y virtualización),making dynamically dispatched calls (interface and virtuals),

• realizar llamadas enviadas estáticamente en cualquier código que no sea de su propiedad omaking statically dispatched calls into any code one doesn't own, or

• asignación de memoria.allocating memory.

SpinLocksolo debe usarse después de haber determinado que al hacerlo se mejorará el rendimiento de una aplicación.SpinLock should only be used after you have been determined that doing so will improve an application's performance. También es importante tener en cuenta que SpinLock es un tipo de valor, por motivos de rendimiento.It is also important to note that SpinLock is a value type, for performance reasons. Por esta razón, debe tener mucho cuidado de no copiar accidentalmente una SpinLock instancia, ya que las dos instancias (el original y la copia) serían totalmente independientes entre sí, lo que podría provocar un comportamiento incorrecto de la aplicación.For this reason, you must be very careful not to accidentally copy a SpinLock instance, as the two instances (the original and the copy) would then be completely independent of one another, which would likely lead to erroneous behavior of the application. Si se SpinLock debe pasar una instancia, debe pasarse por referencia en lugar de por valor.If a SpinLock instance must be passed around, it should be passed by reference rather than by value.

No almacene SpinLock instancias en campos de solo lectura.Do not store SpinLock instances in readonly fields.

## Constructores

 Inicializa una nueva instancia de la estructura SpinLock con la opción de realizar el seguimiento de los identificadores de subprocesos para mejorar la depuración.Initializes a new instance of the SpinLock structure with the option to track thread IDs to improve debugging.

 Obtiene un valor que indica si un subproceso mantiene actualmente el bloqueo.Gets whether the lock is currently held by any thread. Obtiene un valor que indica si el subproceso actual mantiene actualmente el bloqueo.Gets whether the lock is held by the current thread. Obtiene un valor que indica si el seguimiento de propiedad de subprocesos está habilitado para esta instancia.Gets whether thread ownership tracking is enabled for this instance.

## Métodos

 Adquiere el bloqueo de manera confiable de modo que, incluso si se produce una excepción en la llamada al método, se pueda examinar `lockTaken` de manera confiable para determinar si se adquirió el bloqueo.Acquires the lock in a reliable manner, such that even if an exception occurs within the method call, `lockTaken` can be examined reliably to determine whether the lock was acquired. Libera el bloqueo.Releases the lock. Libera el bloqueo.Releases the lock. Intenta adquirir el bloqueo de manera confiable de modo que, incluso si se produce una excepción en la llamada al método, se pueda examinar `lockTaken` de manera confiable para determinar si se adquirió el bloqueo.Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within the method call, `lockTaken` can be examined reliably to determine whether the lock was acquired. Intenta adquirir el bloqueo de manera confiable de modo que, incluso si se produce una excepción en la llamada al método, se pueda examinar `lockTaken` de manera confiable para determinar si se adquirió el bloqueo.Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within the method call, `lockTaken` can be examined reliably to determine whether the lock was acquired. Intenta adquirir el bloqueo de manera confiable de modo que, incluso si se produce una excepción en la llamada al método, se pueda examinar `lockTaken` de manera confiable para determinar si se adquirió el bloqueo.Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within the method call, `lockTaken` can be examined reliably to determine whether the lock was acquired.