Semaphore Класс

Определение

Ограничивает число потоков, которые могут одновременно обращаться к ресурсу или пулу ресурсов.

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
Наследование
Semaphore
Наследование
Атрибуты

Примеры

В следующем примере кода создается семафор с максимальным числом 3 и начальным числом, равным нулю. В примере запускается пять потоков, которые блокируют ожидание семафора. Поток main использует перегрузку Release(Int32) метода, чтобы увеличить количество семафоров до максимального значения, позволяя трем потокам войти в семафор. Каждый поток использует Thread.Sleep метод для ожидания одной секунды для имитации работы, а затем вызывает перегрузку Release() метода, чтобы освободить семафор. При каждом освобождении семафора отображается предыдущее число семафоров. Сообщения консоли отслеживают использование семафора. Имитированный рабочий интервал немного увеличивается для каждого потока, чтобы упростить чтение выходных данных.

#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

Комментарии

Используйте класс для Semaphore управления доступом к пулу ресурсов. Потоки входят в семафор, вызывая WaitOne метод , который наследуется от WaitHandle класса , и освобождают семафор путем вызова Release метода .

Количество семафоров уменьшается каждый раз, когда поток входит в семафор, и увеличивается, когда поток освобождает семафор. Если счетчик равен нулю, последующие запросы блокируются до тех пор, пока другие потоки не отпустит семафор. Когда все потоки отпустили семафор, счетчик будет иметь максимальное значение, указанное при создании семафора.

Нет гарантированного порядка, например FIFO или LIFO, в котором заблокированные потоки входят в семафор.

Поток может войти в семафор несколько раз, многократно вызывая WaitOne метод . Чтобы освободить некоторые или все из этих записей, поток может несколько раз вызвать перегрузку метода без Release() параметров или вызвать перегрузку Release(Int32) метода, указывающую количество записей, которые необходимо освободить.

Класс Semaphore не применяет удостоверение потока при вызовах или WaitOneRelease. Программист отвечает за то, чтобы потоки не выпускали семафор слишком много раз. Например предположим, что семафор имеет максимальное значение счетчика равное двум, а два потока A и B входят в семафор. Если ошибка программирования в потоке B вызывает его Release дважды, оба вызова будут выполнены успешно. Счетчик на семафоре переполнен, и если поток A вызывает Release, SemaphoreFullException создается исключение.

Семафоры бывают двух типов: локальные семафоры и именованные системные семафоры. Если объект создается Semaphore с помощью конструктора, принимающего имя, он связывается с семафором операционной системы с таким именем. Именованные системные семафоры видны во всей операционной системе и могут использоваться для синхронизации действий процессов. Можно создать несколько Semaphore объектов, представляющих один и тот же именованный системный семафор, и использовать OpenExisting метод для открытия существующего именованного системного семафора.

Локальный семафор существует только в рамках процесса. Его может использовать любой поток в вашем процессе, имеющий ссылку на локальный объект Semaphore. Каждый Semaphore объект является отдельным локальным семафором.

Внимание!

По умолчанию именованный семафор не ограничивается пользователем, который его создал. Другие пользователи могут открывать и использовать семафор, в том числе вмешиваться в семафор, приобретая семафор несколько раз и не отпуская его. Чтобы ограничить доступ для определенных пользователей, можно использовать перегрузку конструктора или SemaphoreAcl и передать SemaphoreSecurity в при создании именованного семафора. Избегайте использования именованных семафоров без ограничений доступа в системах, в которых могут выполняться ненадежные пользователи, выполняющие код.

Конструкторы

Semaphore(Int32, Int32)

Инициализирует новый экземпляр класса Semaphore, задающий начальное количество входов и максимальное количество одновременных входов.

Semaphore(Int32, Int32, String)

Инициализирует новый экземпляр класса Semaphore, задающий начальное количество входов и максимальное количество одновременных входов, а также при необходимости имя объекта системного семафора.

Semaphore(Int32, Int32, String, Boolean)

Инициализирует новый экземпляр класса Semaphore, задающий начальное количество входов и максимальное количество одновременных входов, а также при необходимости задающий имя объекта системного семафора и переменную, получающую значение, которое указывает, был ли создан новый системный семафор.

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

Инициализирует новый экземпляр класса Semaphore, задающий начальное количество входов и максимальное количество одновременных входов, а также при необходимости задает имя объекта системного семафора, переменную, которая получает значение, указывающее, был ли создан новый системный семафор, и управление безопасным доступом для системного семафора.

Поля

WaitTimeout

Указывает, что время ожидания операции WaitAny(WaitHandle[], Int32, Boolean) истекло до получения сигнала каким-либо из дескрипторов ожидания. Это поле является константой.

(Унаследовано от WaitHandle)

Свойства

Handle
Устаревшие..
Устаревшие..

Возвращает или задает собственный дескриптор операционной системы.

(Унаследовано от WaitHandle)
SafeWaitHandle

Возвращает или задает собственный дескриптор операционной системы.

(Унаследовано от WaitHandle)

Методы

Close()

Освобождает все ресурсы, удерживаемые текущим объектом WaitHandle.

(Унаследовано от WaitHandle)
CreateObjRef(Type)

Создает объект, который содержит всю необходимую информацию для создания прокси-сервера, используемого для взаимодействия с удаленным объектом.

(Унаследовано от MarshalByRefObject)
Dispose()

Освобождает все ресурсы, используемые текущим экземпляром класса WaitHandle.

(Унаследовано от WaitHandle)
Dispose(Boolean)

При переопределении в производном классе освобождает неуправляемые ресурсы, используемые объектом WaitHandle, и при необходимости освобождает управляемые ресурсы.

(Унаследовано от WaitHandle)
Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
GetAccessControl()

Возвращает настройки управления доступом для именованного системного семафора.

GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetLifetimeService()
Устаревшие..

Извлекает объект обслуживания во время существования, который управляет политикой времени существования данного экземпляра.

(Унаследовано от MarshalByRefObject)
GetType()

Возвращает объект Type для текущего экземпляра.

(Унаследовано от Object)
InitializeLifetimeService()
Устаревшие..

Получает объект службы времени существования для управления политикой времени существования для этого экземпляра.

(Унаследовано от MarshalByRefObject)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
MemberwiseClone(Boolean)

Создает неполную копию текущего объекта MarshalByRefObject.

(Унаследовано от MarshalByRefObject)
OpenExisting(String)

Открывает указанный именованный семафор, если он уже существует.

OpenExisting(String, SemaphoreRights)

Открывает указанный именованный семафор, если он уже существует, с требуемыми правами доступа.

Release()

Выходит из семафора и возвращает последнее значение счетчика.

Release(Int32)

Выходит из семафора указанное число раз и возвращает последнее значение счетчика.

SetAccessControl(SemaphoreSecurity)

Задает безопасность управления доступом для именованного системного семафора.

ToString()

Возвращает строку, представляющую текущий объект.

(Унаследовано от Object)
TryOpenExisting(String, Semaphore)

Открывает указанный именованный семафор, если он уже существует, и возвращает значение, указывающее, успешно ли выполнена операция.

TryOpenExisting(String, SemaphoreRights, Semaphore)

Открывает заданный именованный семафор, если он уже существует, с требуемыми правами доступа, и возвращает значение, указывающее, успешно ли выполнена операция.

WaitOne()

Блокирует текущий поток до получения сигнала объектом WaitHandle.

(Унаследовано от WaitHandle)
WaitOne(Int32)

Блокирует текущий поток до получения текущим дескриптором WaitHandle сигнала, используя 32-разрядное целое число со знаком для указания интервала времени в миллисекундах.

(Унаследовано от WaitHandle)
WaitOne(Int32, Boolean)

Блокирует текущий поток до получения сигнала текущим объектом WaitHandle, используя 32-разрядное целое число со знаком для задания периода времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

(Унаследовано от WaitHandle)
WaitOne(TimeSpan)

Блокирует текущий поток до получения сигнала текущим экземпляром, используя значение типа TimeSpan для указания интервала времени.

(Унаследовано от WaitHandle)
WaitOne(TimeSpan, Boolean)

Блокирует текущий поток до получения сигнала текущим экземпляром, используя значение типа TimeSpan для задания интервала времени и указывая, следует ли выйти из домена синхронизации до начала ожидания.

(Унаследовано от WaitHandle)

Явные реализации интерфейса

IDisposable.Dispose()

Этот API поддерживает инфраструктуру продукта и не предназначен для использования непосредственно из программного кода.

Освобождает все ресурсы, занятые модулем WaitHandle.

(Унаследовано от WaitHandle)

Методы расширения

GetAccessControl(Semaphore)

Возвращает дескрипторы безопасности для указанного semaphore.

SetAccessControl(Semaphore, SemaphoreSecurity)

Задает дескрипторы безопасности для указанного семафора.

GetSafeWaitHandle(WaitHandle)

Возвращает безопасный дескриптор для собственного дескриптора ожидания операционной системы.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

Задает безопасный дескриптор для собственного дескриптора ожидания операционной системы.

Применяется к

Потокобезопасность

Данный тип потокобезопасен.

См. также раздел