Exportar (0) Imprimir
Expandir todo

Semaphore (Clase)

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

Espacio de nombres: System.Threading
Ensamblado: System (en system.dll)

[ComVisibleAttribute(false)] 
public sealed class Semaphore : WaitHandle
/** @attribute ComVisibleAttribute(false) */ 
public final class Semaphore extends WaitHandle
ComVisibleAttribute(false) 
public final class Semaphore extends WaitHandle
No aplicable.

NotaNota:

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

Utilice la clase Semaphore para controlar el acceso a un grupo de recursos. Para entrar en el semáforo, los subprocesos llaman al método WaitOne, que se hereda de la clase WaitHandle, y para liberarlo llaman al método Release.

El recuento de un semáforo disminuye cada vez que un subproceso entra en él, e incrementa cuando un subproceso lo libera. 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 está en el valor máximo especificado al crear el semáforo.

No hay ningún orden garantizado, como FIFO o LIFO, para la entrada de los subprocesos bloqueados en el semáforo.

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

La clase Semaphore no exige la identidad del subproceso en las llamadas a WaitOne o Release. Es responsabilidad del programador garantizar que los subprocesos no liberen el semáforo demasiadas veces. Por ejemplo, supongamos que un semáforo tiene un recuento máximo de dos y que entran en el semáforo los subprocesos A y B. Si un error de programación del subproceso B hace que llame a Release dos veces, las dos llamadas tienen éxito. Se alcanza el recuento máximo del semáforo y, si el subproceso A llama posteriormente a Release, se genera una excepción SemaphoreFullException.

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

Un semáforo local sólo existe dentro del proceso. Puede utilizarlo cualquier subproceso del proceso que contenga una referencia al objeto Semaphore local. Cada objeto Semaphore es un semáforo local distinto.

En el ejemplo de código siguiente se crea un semáforo con un número máximo de tres y un recuento inicial de cero. El ejemplo inicia cinco subprocesos que se bloquean en espera del semáforo. El subproceso principal aumenta el recuento del semáforo a su máximo, mediante la sobrecarga del método Release(Int32), lo que permite la entrada de tres subprocesos en el semáforo. Los subprocesos utilizan el método System.Threading.Thread.Sleep para esperar un segundo, simular que trabajan y, a continuación, llamar a la sobrecarga de método Release para liberar el semáforo. Cada vez que se libera el semáforo, se muestra el recuento del semáforo anterior. Los mensajes de consola llevan un seguimiento del uso del semáforo. El intervalo de trabajo simulado aumenta ligeramente por cada subproceso, lo que facilita la lectura del resultado.

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(0, 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(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());
    }
}

import System.*;
import 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(String[] args)
    {
        // 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 (int i = 1; i <= 5; i++) {
            System.Threading.Thread t = new System.Threading.Thread(new 
                ParameterizedThreadStart(Worker));
            // Start the thread, passing the number.
            //
            t.Start((Int32)i);
        }
        // Wait for half a second, to allow all the
        // threads to start and to block on the semaphore.
        //
        System.Threading.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.");
    } //main

    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(_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.
        //
        System.Threading.Thread.Sleep(1000 + padding);

        Console.WriteLine("Thread {0} releases the semaphore.", num);
        Console.WriteLine("Thread {0} previous semaphore count: {1}", num, 
            (Int32)_pool.Release());
    } //Worker
} //Example

Los miembros estáticos públicos (Shared en Visual Basic) de este tipo son seguros para la ejecución de subprocesos. No se garantiza que los miembros de instancias sean seguros para la ejecución de subprocesos.

Windows 98, Windows 2000 Service Pack 4, Windows Millennium, Windows Server 2003, Windows XP Media Center, Windows XP Professional x64, Windows XP SP2, Windows XP Starter

Microsoft .NET Framework 3.0 es compatible con Windows Vista, Microsoft Windows XP SP2 y Windows Server 2003 SP1.

.NET Framework

Compatible con: 3.0, 2.0
Mostrar:
© 2014 Microsoft