Exportar (0) Imprimir
Expandir todo
Este artículo proviene de un motor de traducción automática. Mueva el puntero sobre las frases del artículo para ver el texto original. Más información.
Traducción
Original
Personas que lo han encontrado útil: 1 de 1 - Valorar este tema

SpinLock (Estructura)

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.

Espacio de nombres:  System.Threading
Ensamblado:  mscorlib (en mscorlib.dll)
[ComVisibleAttribute(false)]
[HostProtectionAttribute(SecurityAction.LinkDemand, Synchronization = true, 
	ExternalThreading = true)]
public struct SpinLock

El tipo SpinLock expone los siguientes miembros.

  NombreDescripción
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsSpinLockInicializa 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.
Arriba
  NombreDescripción
Propiedad públicaCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsIsHeldObtiene un valor que indica si un subproceso mantiene actualmente el bloqueo.
Propiedad públicaCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsIsHeldByCurrentThreadObtiene un valor que indica si el subproceso actual mantiene actualmente el bloqueo.
Propiedad públicaCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsIsThreadOwnerTrackingEnabledObtiene un valor que indica si el seguimiento de propiedad de subprocesos está habilitado para esta instancia.
Arriba
  NombreDescripción
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsEnterAdquiere 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.
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsEqualsIndica si esta instancia y un objeto especificado son iguales. (Se hereda de ValueType).
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsExit()Libera el bloqueo.
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsExit(Boolean)Libera el bloqueo.
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsGetHashCodeDevuelve el código hash de esta instancia. (Se hereda de ValueType).
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsGetType Obtiene el Typede la instancia actual. (Se hereda de Object).
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsToStringDevuelve el nombre de tipo completo de esta instancia. (Se hereda de ValueType).
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsTryEnter(Boolean)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.
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsTryEnter(Int32, Boolean)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.
Método públicoCompatible con Biblioteca de clases portableCompatible con .NET para aplicaciones de la Tienda WindowsTryEnter(TimeSpan, Boolean)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.
Arriba

Para obtener un ejemplo de cómo usar un bloqueo por subproceso, vea Cómo: Utilizar SpinLock para la sincronización de bajo nivel.

Los bloqueos por subproceso se pueden utilizar para bloqueos en el nivel de hoja en los que la asignación de objetos implícita al utilizar un Monitor, por tamaño o debido a la presión de la recolección de elementos no utilizados, es demasiado cara. Un bloqueo por subproceso puede ser útil para evitar bloqueos; sin embargo, si espera una cantidad significativa de bloqueos, probablemente no debería utilizar bloqueos por subproceso debido al giro excesivo. El giro puede ser beneficioso cuando los bloqueos son específicos y numerosos (por ejemplo, un bloqueo por nodo en una lista vinculada) y también cuando el tiempo durante el que se mantiene el bloqueo es siempre muy corto. En general, cuando se mantiene un bloqueo por subproceso, se debería evitar cualquiera de estas acciones:

  • bloqueo,

  • llamar a algo que se puede bloquear por sí mismo,

  • mantener más de un bloqueo por subproceso a la vez,

  • realizando llamadas enviadas dinámicamente (interfaz y virtuales)

  • realizando llamadas enviadas estáticamente en cualquier código que no se posee, o

  • asignando memoria.

Solo se debería utilizar SpinLock una vez determinado que, si se hace, mejorará el rendimiento de una aplicación. También es importante tener en cuenta que SpinLock es un tipo de valor, por razones de rendimiento. Por esta razón, debe tener mucho cuidado de no copiar una instancia de SpinLock accidentalmente, ya que las dos instancias (la original y la copia) serían completamente independientes entre sí, lo cual probablemente conduciría a un comportamiento erróneo de la aplicación. Si se debe hacer circular una instancia de SpinLock, se debería pasar por referencia en lugar de por valor.

No almacene instancias de SpinLock en campos de solo lectura.

NotaNota

El atributo HostProtectionAttribute aplicado a este tipo o miembro tiene el valor de propiedad Resources siguiente: Synchronization | ExternalThreading. El atributo HostProtectionAttribute no afecta a las aplicaciones de escritorio (que normalmente se inician haciendo doble clic en un icono, escribiendo un comando o introduciendo una dirección URL en el explorador). Para obtener más información, vea la clase HostProtectionAttribute o Programación en SQL Server y atributos de protección de host.

En el ejemplo anterior se muestra cómo utilizar SpinLock.


using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


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
        // access to sb with a SpinLock.
        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
    //      SpinLock.IsHeldByCurrentThread
    //      SpinLock.IsThreadOwnerTrackingEnabled
    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;

        Task taskA = Task.Factory.StartNew(() =>
        {
            try
            {
                sl.Enter(ref lockTaken);
                Console.WriteLine("Task A: entered SpinLock");
                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
                // taskB.)
                mre2.Wait();
            }
            finally
            {
                if (lockTaken) sl.Exit();
            }
        });

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

            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
        Task.WaitAll(taskA, taskB);
        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
        Console.WriteLine("main thread id = {0}", Thread.CurrentThread.ManagedThreadId);

        // 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
        Task worker = Task.Factory.StartNew(() =>
        {
            Console.WriteLine("worker task thread id = {0} (should be different than main thread id)",
                Thread.CurrentThread.ManagedThreadId);

            // 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
        // a different thread can exit the SpinLock created (without thread tracking) on your thread.
        mres.Wait();

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

}


.NET Framework

Compatible con: 4.5, 4

.NET Framework Client Profile

Compatible con: 4

Biblioteca de clases portable

Compatible con: Biblioteca de clases portable

.NET para aplicaciones de la Tienda Windows

Compatible con: Windows 8

Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (no se admite el rol Server Core), Windows Server 2008 R2 (se admite el rol Server Core con SP1 o versiones posteriores; no se admite Itanium)

.NET Framework no admite todas las versiones de todas las plataformas. Para obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.

Todos los miembros de SpinLock son seguros para subprocesos y se pueden usar desde varios subprocesos simultáneamente.

¿Te ha resultado útil?
(Caracteres restantes: 1500)
Gracias por sus comentarios

Adiciones de comunidad

AGREGAR
Mostrar:
© 2014 Microsoft. Reservados todos los derechos.