Semaphore Classe

Definição

Limita o número de threads que podem acessar um recurso ou um pool de recursos simultaneamente.

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
Herança
Semaphore
Herança
Atributos

Exemplos

O exemplo de código a seguir cria um semáforo com uma contagem máxima de três e uma contagem inicial de zero. O exemplo inicia cinco threads, que bloqueiam a espera pelo semáforo. O thread main usa a sobrecarga do Release(Int32) método para aumentar a contagem de semáforos para o máximo, permitindo que três threads insiram o semáforo. Cada thread usa o Thread.Sleep método para aguardar um segundo, para simular o trabalho e, em seguida, chama a sobrecarga do Release() método para liberar o semáforo. Cada vez que o semáforo é liberado, a contagem de semáforos anterior é exibida. As mensagens do console rastreiam o uso do semáforo. O intervalo de trabalho simulado é ligeiramente aumentado para cada thread, para facilitar a leitura da saída.

#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

Comentários

Use a classe para controlar o Semaphore acesso a um pool de recursos. Os threads inserem o semáforo chamando o WaitOne método , que é herdado da WaitHandle classe , e liberam o semáforo chamando o Release método .

A contagem em um semáforo é decrementada sempre que um thread entra no semáforo e incrementado quando um thread libera o semáforo. Quando a contagem for zero, as solicitações subsequentes serão bloqueadas até que outros threads liberem o semáforo. Quando todos os threads liberam o semáforo, a contagem está no valor máximo especificado quando o semáforo foi criado.

Não há ordem garantida, como FIFO ou LIFO, na qual threads bloqueados entram no semáforo.

Um thread pode inserir o semáforo várias vezes, chamando o WaitOne método repetidamente. Para liberar algumas ou todas essas entradas, o thread pode chamar a sobrecarga de método sem Release() parâmetros várias vezes ou pode chamar a sobrecarga do Release(Int32) método que especifica o número de entradas a serem liberadas.

A Semaphore classe não impõe a identidade de thread em chamadas para WaitOne ou Release. É responsabilidade do programador garantir que os threads não liberem o semáforo muitas vezes. Por exemplo, suponha que um sinal tenha uma contagem máxima de dois, e que o thread A e o thread B insiram o sinal. Se um erro de programação no thread B fizer com que ele chame Release duas vezes, ambas as chamadas serão bem-sucedidas. A contagem no sinal está completa e quando o thread A eventualmente chama Release, uma SemaphoreFullException é lançada.

Semáforos são de dois tipos: semáforos locais e semáforos do sistema nomeados. Se você criar um Semaphore objeto usando um construtor que aceita um nome, ele será associado a um semáforo do sistema operacional desse nome. Os semáforos do sistema nomeados são visíveis em todo o sistema operacional e podem ser usados para sincronizar as atividades dos processos. Você pode criar vários Semaphore objetos que representam o mesmo semáforo do sistema nomeado e pode usar o OpenExisting método para abrir um semáforo de sistema nomeado existente.

Um semáforo local existe somente em seu processo. Ele pode ser usado por qualquer thread em seu processo que tenha referência ao objeto Semaphore local. Cada Semaphore objeto é um semáforo local separado.

Cuidado

Por padrão, um semáforo nomeado não é restrito ao usuário que o criou. Outros usuários podem ser capazes de abrir e usar o semáforo, incluindo interferir no semáforo adquirindo o semáforo várias vezes e não liberando-o. Para restringir o acesso a usuários específicos, você pode usar uma sobrecarga de construtor ou SemaphoreAcl e passar um SemaphoreSecurity ao criar o semáforo nomeado. Evite usar semáforos nomeados sem restrições de acesso em sistemas que podem ter usuários não confiáveis executando código.

Construtores

Semaphore(Int32, Int32)

Inicializa uma nova instância da classe Semaphore, especificando o número inicial de entradas e o número máximo de entradas simultâneas.

Semaphore(Int32, Int32, String)

Inicializa uma nova instância da classe Semaphore, especificando o número inicial de entradas e o número máximo de entradas simultâneas e, opcionalmente, especificando o nome de um objeto de sinal de sistema.

Semaphore(Int32, Int32, String, Boolean)

Inicializa uma nova instância da classe Semaphore, especificando o número inicial de entradas e o número máximo de entradas simultâneas, opcionalmente especificando o nome de um objeto de semáforo de sistema e especificando uma variável que recebe um valor que indica se um novo semáforo do sistema foi criado.

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

Inicializa uma nova instância da classe Semaphore, especificando o número inicial de entradas e o número máximo de entradas simultâneas, opcionalmente especificando o nome de um objeto de semáforo de sistema, especificando uma variável que recebe um valor que indica se um novo semáforo do sistema foi criado e especificando o controle de acesso de segurança para o semáforo do sistema.

Campos

WaitTimeout

Indica que uma operação WaitAny(WaitHandle[], Int32, Boolean) atingiu o tempo limite antes que algum dos identificadores de espera fosse sinalizado. Este campo é constante.

(Herdado de WaitHandle)

Propriedades

Handle
Obsoleto.
Obsoleto.

Obtém ou define o identificador de sistema operacional nativo.

(Herdado de WaitHandle)
SafeWaitHandle

Obtém ou define o identificador de sistema operacional nativo.

(Herdado de WaitHandle)

Métodos

Close()

Libera todos os recursos mantidos pelo WaitHandle atual.

(Herdado de WaitHandle)
CreateObjRef(Type)

Cria um objeto que contém todas as informações relevantes necessárias para gerar um proxy usado para se comunicar com um objeto remoto.

(Herdado de MarshalByRefObject)
Dispose()

Libera todos os recursos usados pela instância atual da classe WaitHandle.

(Herdado de WaitHandle)
Dispose(Boolean)

Quando substituído em uma classe derivada, libera os recursos não gerenciados usados pelo WaitHandle e, opcionalmente, libera os recursos gerenciados.

(Herdado de WaitHandle)
Equals(Object)

Determina se o objeto especificado é igual ao objeto atual.

(Herdado de Object)
GetAccessControl()

Define a segurança de controle de acesso para um semáforo de sistema nomeado.

GetHashCode()

Serve como a função de hash padrão.

(Herdado de Object)
GetLifetimeService()
Obsoleto.

Recupera o objeto de serviço de tempo de vida atual que controla a política de ciclo de vida para esta instância.

(Herdado de MarshalByRefObject)
GetType()

Obtém o Type da instância atual.

(Herdado de Object)
InitializeLifetimeService()
Obsoleto.

Obtém um objeto de serviço de tempo de vida para controlar a política de tempo de vida para essa instância.

(Herdado de MarshalByRefObject)
MemberwiseClone()

Cria uma cópia superficial do Object atual.

(Herdado de Object)
MemberwiseClone(Boolean)

Cria uma cópia superficial do objeto MarshalByRefObject atual.

(Herdado de MarshalByRefObject)
OpenExisting(String)

Abre o semáforo nomeado especificado, caso ele já exista.

OpenExisting(String, SemaphoreRights)

Abre o semáforo nomeado especificado, caso ele já exista, com o acesso de segurança desejado.

Release()

Sai do sinal e retorna à contagem anterior.

Release(Int32)

Sai do sinal de um número de vezes especificado e retorna à contagem anterior.

SetAccessControl(SemaphoreSecurity)

Define a segurança de controle de acesso para um semáforo de sistema nomeado.

ToString()

Retorna uma cadeia de caracteres que representa o objeto atual.

(Herdado de Object)
TryOpenExisting(String, Semaphore)

Abre o semáforo nomeado especificado, caso ele já exista e retorna um valor que indica se a operação foi bem-sucedida.

TryOpenExisting(String, SemaphoreRights, Semaphore)

Se o semáforo nomeado especificado já existe, abre-o com o acesso de segurança desejado e retorna um valor que indica se a operação foi bem-sucedida.

WaitOne()

Bloqueia o thread atual até que o WaitHandle atual receba um sinal.

(Herdado de WaitHandle)
WaitOne(Int32)

Bloqueia o thread atual até que o WaitHandle atual receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo em milissegundos.

(Herdado de WaitHandle)
WaitOne(Int32, Boolean)

Bloqueia o thread atual até que o WaitHandle atual receba um sinal, usando um inteiro com sinal de 32 bits para especificar o intervalo de tempo e especificar se sairá do domínio de sincronização antes da espera.

(Herdado de WaitHandle)
WaitOne(TimeSpan)

Bloqueia o thread atual até que a instância atual receba um sinal, usando um TimeSpan para especificar o intervalo de tempo.

(Herdado de WaitHandle)
WaitOne(TimeSpan, Boolean)

Bloqueia o thread atual até que a instância atual receba um sinal, usando um TimeSpan para especificar o intervalo de tempo e especificar se sairá do domínio de sincronização antes da espera.

(Herdado de WaitHandle)

Implantações explícitas de interface

IDisposable.Dispose()

Esta API dá suporte à infraestrutura do produto e não deve ser usada diretamente do seu código.

Libera todos os recursos usados pelo WaitHandle.

(Herdado de WaitHandle)

Métodos de Extensão

GetAccessControl(Semaphore)

Retorna os descritores de segurança para o semaphore especificado.

SetAccessControl(Semaphore, SemaphoreSecurity)

Define os descritores de segurança para o semáforo especificado.

GetSafeWaitHandle(WaitHandle)

Obtém o identificador seguro para um identificador de espera nativo do sistema operacional.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Define um identificador seguro para um identificador de espera do sistema operacional nativo.

Aplica-se a

Acesso thread-safe

Este tipo é thread-safe.

Confira também