Semaphore Clase

Definición

Limita el número de subprocesos que pueden tener acceso a un recurso o grupo de recursos simultáneamente.

public ref class Semaphore sealed : System::Threading::WaitHandle
public sealed class Semaphore : System.Threading.WaitHandle
[System.Runtime.InteropServices.ComVisible(false)]
public sealed class Semaphore : System.Threading.WaitHandle
type Semaphore = class
    inherit WaitHandle
[<System.Runtime.InteropServices.ComVisible(false)>]
type Semaphore = class
    inherit WaitHandle
Public NotInheritable Class Semaphore
Inherits WaitHandle
Herencia
Semaphore
Herencia
Atributos

Ejemplos

En el ejemplo de código siguiente se crea un semáforo con un recuento máximo de tres y un recuento inicial de cero. En el ejemplo se inician cinco subprocesos, que bloquean la espera del semáforo. El subproceso principal usa la sobrecarga del Release(Int32) método para aumentar el número de semáforos a su máximo, lo que permite que tres subprocesos entren en el semáforo. Cada subproceso usa el Thread.Sleep método para esperar un segundo, para simular el trabajo y, a continuación, llama a la sobrecarga del Release() método para liberar el semáforo. Cada vez que se libera el semáforo, se muestra el recuento de semáforos anterior. Los mensajes de la consola realizan un seguimiento del uso del semáforo. El intervalo de trabajo simulado aumenta ligeramente para cada subproceso, para facilitar la lectura de la salida.

#using <System.dll>
using namespace System;
using namespace System::Threading;

public ref class Example
{
private:
   // A semaphore that simulates a limited resource pool.
   //
   static Semaphore^ _pool;

   // A padding interval to make the output more orderly.
   static int _padding;

public:
   static void Main()
   {
      // Create a semaphore that can satisfy up to three
      // concurrent requests. Use an initial count of zero,
      // so that the entire semaphore count is initially
      // owned by the main program thread.
      //
      _pool = gcnew Semaphore( 0,3 );
      
      // Create and start five numbered threads.
      //
      for ( int i = 1; i <= 5; i++ )
      {
         Thread^ t = gcnew Thread(
            gcnew ParameterizedThreadStart( Worker ) );
         
         // Start the thread, passing the number.
         //
         t->Start( i );
      }
      
      // Wait for half a second, to allow all the
      // threads to start and to block on the semaphore.
      //
      Thread::Sleep( 500 );
      
      // The main thread starts out holding the entire
      // semaphore count. Calling Release(3) brings the
      // semaphore count back to its maximum value, and
      // allows the waiting threads to enter the semaphore,
      // up to three at a time.
      //
      Console::WriteLine( L"Main thread calls Release(3)." );
      _pool->Release( 3 );

      Console::WriteLine( L"Main thread exits." );
   }

private:
   static void Worker( Object^ num )
   {
      // Each worker thread begins by requesting the
      // semaphore.
      Console::WriteLine( L"Thread {0} begins and waits for the semaphore.", num );
      _pool->WaitOne();
      
      // A padding interval to make the output more orderly.
      int padding = Interlocked::Add( _padding, 100 );

      Console::WriteLine( L"Thread {0} enters the semaphore.", num );
      
      // The thread's "work" consists of sleeping for
      // about a second. Each thread "works" a little
      // longer, just to make the output more orderly.
      //
      Thread::Sleep( 1000 + padding );

      Console::WriteLine( L"Thread {0} releases the semaphore.", num );
      Console::WriteLine( L"Thread {0} previous semaphore count: {1}",
         num, _pool->Release() );
   }
};
using System;
using System.Threading;

public class Example
{
    // A semaphore that simulates a limited resource pool.
    //
    private static Semaphore _pool;

    // A padding interval to make the output more orderly.
    private static int _padding;

    public static void Main()
    {
        // Create a semaphore that can satisfy up to three
        // concurrent requests. Use an initial count of zero,
        // so that the entire semaphore count is initially
        // owned by the main program thread.
        //
        _pool = new Semaphore(initialCount: 0, maximumCount: 3);

        // Create and start five numbered threads. 
        //
        for(int i = 1; i <= 5; i++)
        {
            Thread t = new Thread(new ParameterizedThreadStart(Worker));

            // Start the thread, passing the number.
            //
            t.Start(i);
        }

        // Wait for half a second, to allow all the
        // threads to start and to block on the semaphore.
        //
        Thread.Sleep(500);

        // The main thread starts out holding the entire
        // semaphore count. Calling Release(3) brings the 
        // semaphore count back to its maximum value, and
        // allows the waiting threads to enter the semaphore,
        // up to three at a time.
        //
        Console.WriteLine("Main thread calls Release(3).");
        _pool.Release(releaseCount: 3);

        Console.WriteLine("Main thread exits.");
    }

    private static void Worker(object num)
    {
        // Each worker thread begins by requesting the
        // semaphore.
        Console.WriteLine("Thread {0} begins " +
            "and waits for the semaphore.", num);
        _pool.WaitOne();

        // A padding interval to make the output more orderly.
        int padding = Interlocked.Add(ref _padding, 100);

        Console.WriteLine("Thread {0} enters the semaphore.", num);
        
        // The thread's "work" consists of sleeping for 
        // about a second. Each thread "works" a little 
        // longer, just to make the output more orderly.
        //
        Thread.Sleep(1000 + padding);

        Console.WriteLine("Thread {0} releases the semaphore.", num);
        Console.WriteLine("Thread {0} previous semaphore count: {1}",
            num, _pool.Release());
    }
}
Imports System.Threading

Public Class Example

    ' A semaphore that simulates a limited resource pool.
    '
    Private Shared _pool As Semaphore

    ' A padding interval to make the output more orderly.
    Private Shared _padding As Integer

    <MTAThread> _
    Public Shared Sub Main()
        ' Create a semaphore that can satisfy up to three
        ' concurrent requests. Use an initial count of zero,
        ' so that the entire semaphore count is initially
        ' owned by the main program thread.
        '
        _pool = New Semaphore(0, 3)

        ' Create and start five numbered threads. 
        '
        For i As Integer = 1 To 5
            Dim t As New Thread(New ParameterizedThreadStart(AddressOf Worker))
            'Dim t As New Thread(AddressOf Worker)

            ' Start the thread, passing the number.
            '
            t.Start(i)
        Next i

        ' Wait for half a second, to allow all the
        ' threads to start and to block on the semaphore.
        '
        Thread.Sleep(500)

        ' The main thread starts out holding the entire
        ' semaphore count. Calling Release(3) brings the 
        ' semaphore count back to its maximum value, and
        ' allows the waiting threads to enter the semaphore,
        ' up to three at a time.
        '
        Console.WriteLine("Main thread calls Release(3).")
        _pool.Release(3)

        Console.WriteLine("Main thread exits.")
    End Sub

    Private Shared Sub Worker(ByVal num As Object)
        ' Each worker thread begins by requesting the
        ' semaphore.
        Console.WriteLine("Thread {0} begins " _
            & "and waits for the semaphore.", num)
        _pool.WaitOne()

        ' A padding interval to make the output more orderly.
        Dim padding As Integer = Interlocked.Add(_padding, 100)

        Console.WriteLine("Thread {0} enters the semaphore.", num)
        
        ' The thread's "work" consists of sleeping for 
        ' about a second. Each thread "works" a little 
        ' longer, just to make the output more orderly.
        '
        Thread.Sleep(1000 + padding)

        Console.WriteLine("Thread {0} releases the semaphore.", num)
        Console.WriteLine("Thread {0} previous semaphore count: {1}", _
            num, _
            _pool.Release())
    End Sub
End Class

Comentarios

Use la clase para controlar el Semaphore acceso a un grupo de recursos. Los subprocesos entran en el semáforo mediante una llamada al WaitOne método , que se hereda de la WaitHandle clase y liberan el semáforo llamando al Release método .

El recuento de un semáforo se disminuye cada vez que un subproceso entra en el semáforo e incrementa cuando un subproceso libera el semáforo. Cuando el recuento es cero, las solicitudes posteriores se bloquean hasta que otros subprocesos liberan el semáforo. Cuando todos los subprocesos han liberado el semáforo, el recuento se encuentra en el valor máximo especificado cuando se creó el semáforo.

No hay ningún orden garantizado, como FIFO o LIFO, en el que los subprocesos bloqueados entran en el semáforo.

Un subproceso puede escribir el semáforo varias veces llamando al WaitOne método repetidamente. Para liberar algunas o todas estas entradas, el subproceso puede llamar a la sobrecarga del método sin Release() parámetros varias veces, o bien puede llamar a la sobrecarga del Release(Int32) método que especifica el número de entradas que se van a liberar.

La Semaphore clase no aplica la identidad del subproceso en las llamadas a WaitOne o Release. Es responsabilidad del programador asegurarse de que los subprocesos no liberan el semáforo demasiadas veces. Por ejemplo, supongamos que un semáforo tiene un recuento máximo de dos y que los subprocesos A y B entran el semáforo. Si un error de programación en el subproceso B hace que llame a Release dos veces, ambas llamadas tendrán éxito. El recuento del semáforo está lleno y cuando el subproceso A finalmente llama a Release, se genera SemaphoreFullException.

Los semáforos son de dos tipos: semáforos locales y semáforos del sistema con nombre. Si crea un Semaphore objeto mediante un constructor que acepta un nombre, está asociado a un semáforo del sistema operativo de ese nombre. Los semáforos del sistema con nombre son visibles en todo el sistema operativo y se pueden usar para sincronizar las actividades de los procesos. Puede crear varios Semaphore objetos que representen el mismo semáforo del sistema con nombre y puede usar el OpenExisting método para abrir un semáforo del sistema con nombre existente.

Un semáforo local solo existe dentro del proceso. La puede usar cualquier subproceso del proceso que tenga una referencia al objeto Semaphore local. Cada Semaphore objeto es un semáforo local independiente.

Precaución

De forma predeterminada, un semáforo con nombre no está restringido al usuario que lo creó. Es posible que otros usuarios puedan abrir y usar el semáforo, incluida la interferencia con el semáforo al adquirir el semáforo varias veces y no liberarlo. Para restringir el acceso a usuarios específicos, puede usar una sobrecarga de constructor o SemaphoreAcl pasar un SemaphoreSecurity al crear el semáforo con nombre. Evite usar semáforos con nombre sin restricciones de acceso en sistemas que puedan tener usuarios que no son de confianza que ejecuten código.

Constructores

Semaphore(Int32, Int32)

Inicializa una nueva instancia de la clase Semaphore, que especifica el número inicial de entradas y el número máximo de entradas simultáneas.

Semaphore(Int32, Int32, String)

Inicializa una nueva instancia de la clase Semaphore, que especifica el número inicial de entradas y el número máximo de entradas simultáneas, y especificando de forma opcional el nombre de un objeto semáforo de sistema.

Semaphore(Int32, Int32, String, Boolean)

Inicializa una instancia nueva de la clase Semaphore, especificando el número inicial de entradas y el número máximo de entradas simultáneas, especificando de forma opcional el nombre de un objeto semáforo de sistema y especificando una variable que recibe un valor que indica si se creó un semáforo del sistema nuevo.

Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity)

Inicializa una instancia nueva de la clase Semaphore, especificando el número inicial de entradas y el número máximo de entradas simultáneas, especificando de forma opcional el nombre de un objeto semáforo de sistema, especificando una variable que recibe un valor que indica si se creó un semáforo del sistema y especificando la seguridad de control de acceso para el semáforo del sistema.

Campos

WaitTimeout

Indica que una operación WaitAny(WaitHandle[], Int32, Boolean) ha superado el tiempo de espera antes de que se señalara un identificador de espera. Este campo es constante.

(Heredado de WaitHandle)

Propiedades

Handle
Obsoletos.
Obsoletos.

Obtiene o establece el identificador del sistema operativo nativo.

(Heredado de WaitHandle)
SafeWaitHandle

Obtiene o establece el identificador del sistema operativo nativo.

(Heredado de WaitHandle)

Métodos

Close()

Libera todos los recursos mantenidos por el objeto WaitHandle actual.

(Heredado de WaitHandle)
CreateObjRef(Type)

Crea un objeto que contiene toda la información relevante necesaria para generar un proxy utilizado para comunicarse con un objeto remoto.

(Heredado de MarshalByRefObject)
Dispose()

Libera todos los recursos usados por la instancia actual de la clase WaitHandle.

(Heredado de WaitHandle)
Dispose(Boolean)

Cuando se reemplaza en una clase derivada, libera los recursos no administrados que usa WaitHandle y, de forma opcional, libera los recursos administrados.

(Heredado de WaitHandle)
Equals(Object)

Determina si el objeto especificado es igual que el objeto actual.

(Heredado de Object)
GetAccessControl()

Obtiene la seguridad de control de acceso para un semáforo de sistema con nombre.

GetHashCode()

Sirve como la función hash predeterminada.

(Heredado de Object)
GetLifetimeService()
Obsoletos.

Recupera el objeto de servicio de duración actual que controla la directiva de duración de esta instancia.

(Heredado de MarshalByRefObject)
GetType()

Obtiene el Type de la instancia actual.

(Heredado de Object)
InitializeLifetimeService()
Obsoletos.

Obtiene un objeto de servicio de duración para controlar la directiva de duración de esta instancia.

(Heredado de MarshalByRefObject)
MemberwiseClone()

Crea una copia superficial del Object actual.

(Heredado de Object)
MemberwiseClone(Boolean)

Crea una copia superficial del objeto MarshalByRefObject actual.

(Heredado de MarshalByRefObject)
OpenExisting(String)

Abre el semáforo con nombre especificado, si ya existe.

OpenExisting(String, SemaphoreRights)

Abre el semáforo con nombre especificado, si ya existe, con el acceso de seguridad deseado.

Release()

Sale del semáforo y devuelve el recuento anterior.

Release(Int32)

Sale del semáforo un número especificado de veces y devuelve el recuento anterior.

SetAccessControl(SemaphoreSecurity)

Establece la seguridad de control de acceso para un semáforo de sistema con nombre.

ToString()

Devuelve una cadena que representa el objeto actual.

(Heredado de Object)
TryOpenExisting(String, Semaphore)

Abre el semáforo con nombre especificado, si ya existe, y devuelve un valor que indica si la operación se realizó correctamente.

TryOpenExisting(String, SemaphoreRights, Semaphore)

Abre el semáforo con nombre especificado, si ya existe, con el acceso de seguridad deseado, y devuelve un valor que indica si la operación se realizó correctamente.

WaitOne()

Bloquea el subproceso actual hasta que el objeto WaitHandle actual recibe una señal.

(Heredado de WaitHandle)
WaitOne(Int32)

Bloquea el subproceso actual hasta que el objeto WaitHandle actual recibe una señal, usando un entero de 32 bits con signo para especificar el intervalo de tiempo en milisegundos.

(Heredado de WaitHandle)
WaitOne(Int32, Boolean)

Bloquea el subproceso actual hasta que el objeto WaitHandle actual recibe una señal, usa un entero de 32 bits con signo para determinar el intervalo de tiempo y especifica si hay que salir del dominio de sincronización antes de la espera.

(Heredado de WaitHandle)
WaitOne(TimeSpan)

Bloquea el subproceso actual hasta que la instancia actual recibe una señal, usando TimeSpan para especificar el intervalo de tiempo.

(Heredado de WaitHandle)
WaitOne(TimeSpan, Boolean)

Bloquea el subproceso actual hasta que la instancia actual recibe una señal; usa TimeSpan para determinar el intervalo de tiempo y especifica si hay que abandonar el dominio de sincronización antes de la espera.

(Heredado de WaitHandle)

Implementaciones de interfaz explícitas

IDisposable.Dispose()

Esta API admite la infraestructura de producto y no está pensada para usarse directamente en el código.

Libera todos los recursos que usa WaitHandle.

(Heredado de WaitHandle)

Métodos de extensión

GetAccessControl(Semaphore)

Devuelve los descriptores de seguridad para el objeto semaphore especificado.

SetAccessControl(Semaphore, SemaphoreSecurity)

Establece los descriptores de seguridad para el semáforo especificado.

GetSafeWaitHandle(WaitHandle)

Obtiene el controlador seguro para un identificador de espera del sistema operativo nativo.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Establece un controlador seguro para un identificador de espera del sistema operativo nativo.

Se aplica a

Seguridad para subprocesos

Este tipo es seguro para la ejecución de subprocesos.

Consulte también