Semaphore Class

Definition

限制可同时访问某一资源或资源池的线程数。Limits the number of threads that can access a resource or pool of resources concurrently.

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
Public NotInheritable Class Semaphore
Inherits WaitHandle
Inheritance
Semaphore
Inheritance
Attributes

Examples

下面的代码示例创建一个信号量,其最大计数为3,初始计数为零。The following code example creates a semaphore with a maximum count of three and an initial count of zero. 该示例启动五个线程,这会阻止等待信号量。The example starts five threads, which block waiting for the semaphore. 主线程使用 Release(Int32) 方法重载将信号量计数增加到其最大值,从而允许三个线程进入信号量。The main thread uses the Release(Int32) method overload to increase the semaphore count to its maximum, allowing three threads to enter the semaphore. 每个线程使用 Thread.Sleep 方法来等待一秒,模拟工作,然后调用 Release() 方法重载以释放信号量。Each thread uses the Thread.Sleep method to wait for one second, to simulate work, and then calls the Release() method overload to release the semaphore. 每次释放信号灯时,都将显示以前的信号量计数。Each time the semaphore is released, the previous semaphore count is displayed. 控制台消息跟踪信号量使用。Console messages track semaphore use. 每个线程的模拟工作时间间隔略有增加,使输出更易于读取。The simulated work interval is increased slightly for each thread, to make the output easier to read.

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

Remarks

使用 Semaphore 类控制对资源池的访问。Use the Semaphore class to control access to a pool of resources. 线程通过调用 WaitOne 方法进入信号量,该方法继承自 WaitHandle 类,并通过调用 Release 方法释放信号量。Threads enter the semaphore by calling the WaitOne method, which is inherited from the WaitHandle class, and release the semaphore by calling the Release method.

每次线程进入信号量时,信号量的计数都将减少,并在线程释放信号量时递增。The count on a semaphore is decremented each time a thread enters the semaphore, and incremented when a thread releases the semaphore. 如果计数为零,则后续请求会阻塞,直到其他线程释放信号量。When the count is zero, subsequent requests block until other threads release the semaphore. 当所有线程都已释放信号量后,计数将达到创建信号量时指定的最大值。When all threads have released the semaphore, the count is at the maximum value specified when the semaphore was created.

没有保证的顺序,如 FIFO 或 LIFO,其中阻塞的线程进入信号量。There is no guaranteed order, such as FIFO or LIFO, in which blocked threads enter the semaphore.

通过重复调用 WaitOne 方法,线程可以多次进入信号量。A thread can enter the semaphore multiple times, by calling the WaitOne method repeatedly. 若要释放部分或全部条目,线程可以多次调用无参数 Release() 方法重载,或调用 Release(Int32) 方法重载来指定要释放的项数。To release some or all of these entries, the thread can call the parameterless Release() method overload multiple times, or it can call the Release(Int32) method overload that specifies the number of entries to be released.

Semaphore 类在调用 WaitOneRelease时不强制执行线程标识。The Semaphore class does not enforce thread identity on calls to WaitOne or Release. 编程人员应负责确保线程不会过多地释放信号量。It is the programmer's responsibility to ensure that threads do not release the semaphore too many times. 例如,假定信号量的最大计数为 2 并且线程 A 和线程 B 都进入了该信号量。For example, suppose a semaphore has a maximum count of two, and that thread A and thread B both enter the semaphore. 如果线程 B 中的编程错误导致其调用 Release 两次,则两次调用都将成功。If a programming error in thread B causes it to call Release twice, both calls succeed. 信号灯计数已满,当线程 A 最终调用 Release 时,SemaphoreFullException 抛出。The count on the semaphore is full, and when thread A eventually calls Release, a SemaphoreFullException is thrown.

信号量分为两种类型:本地信号量和命名系统信号量。Semaphores are of two types: local semaphores and named system semaphores. 如果使用接受名称的构造函数创建 Semaphore 对象,则该对象将与该名称的操作系统信号量关联。If you create a Semaphore object using a constructor that accepts a name, it is associated with an operating-system semaphore of that name. 命名系统信号量在整个操作系统中均可见,可用于同步进程的活动。Named system semaphores are visible throughout the operating system, and can be used to synchronize the activities of processes. 可以创建多个表示同一命名系统信号量的 Semaphore 对象,并可以使用 OpenExisting 方法打开现有的已命名系统信号量。You can create multiple Semaphore objects that represent the same named system semaphore, and you can use the OpenExisting method to open an existing named system semaphore.

局部信号量仅存在于进程内。A local semaphore exists only within your process. 进程中引用本地 Semaphore 对象的所有线程都可以使用本地 mutex。It can be used by any thread in your process that has a reference to the local Semaphore object. 每个 Semaphore 对象都是单独的本地信号量。Each Semaphore object is a separate local semaphore.

Constructors

Semaphore(Int32, Int32)

初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数。Initializes a new instance of the Semaphore class, specifying the initial number of entries and the maximum number of concurrent entries.

Semaphore(Int32, Int32, String)

初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,可以选择指定系统信号量对象的名称。Initializes a new instance of the Semaphore class, specifying the initial number of entries and the maximum number of concurrent entries, and optionally specifying the name of a system semaphore object.

Semaphore(Int32, Int32, String, Boolean)

初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,还可以选择指定系统信号量对象的名称,以及指定一个变量来接收指示是否创建了新系统信号量的值。Initializes a new instance of the Semaphore class, specifying the initial number of entries and the maximum number of concurrent entries, optionally specifying the name of a system semaphore object, and specifying a variable that receives a value indicating whether a new system semaphore was created.

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

初始化 Semaphore 类的新实例,并指定初始入口数和最大并发入口数,可以选择指定系统信号量对象的名称,指定一个变量来接收指示是否创建了新系统信号量的值,以及指定系统信号量的安全访问控制。Initializes a new instance of the Semaphore class, specifying the initial number of entries and the maximum number of concurrent entries, optionally specifying the name of a system semaphore object, specifying a variable that receives a value indicating whether a new system semaphore was created, and specifying security access control for the system semaphore.

Fields

WaitTimeout

指示在任何等待句柄终止之前 WaitAny(WaitHandle[], Int32, Boolean) 操作已超时。Indicates that a WaitAny(WaitHandle[], Int32, Boolean) operation timed out before any of the wait handles were signaled. 此字段是常量。This field is constant.

(Inherited from WaitHandle)

Properties

Handle

获取或设置本机操作系统句柄。Gets or sets the native operating system handle.

(Inherited from WaitHandle)
SafeWaitHandle

获取或设置本机操作系统句柄。Gets or sets the native operating system handle.

(Inherited from WaitHandle)

Methods

Close()

释放由当前 WaitHandle 占用的所有资源。Releases all resources held by the current WaitHandle.

(Inherited from WaitHandle)
CreateObjRef(Type)

创建一个对象,该对象包含生成用于与远程对象进行通信的代理所需的全部相关信息。Creates an object that contains all the relevant information required to generate a proxy used to communicate with a remote object.

(Inherited from MarshalByRefObject)
Dispose()

释放由 WaitHandle 类的当前实例占用的所有资源。Releases all resources used by the current instance of the WaitHandle class.

(Inherited from WaitHandle)
Dispose(Boolean)

当在派生类中重写时,释放 WaitHandle 使用的非托管资源,并且可选择释放托管资源。When overridden in a derived class, releases the unmanaged resources used by the WaitHandle, and optionally releases the managed resources.

(Inherited from WaitHandle)
Equals(Object)

确定指定的对象是否等于当前对象。Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetAccessControl()

获取已命名的系统信号量的访问控制安全性。Gets the access control security for a named system semaphore.

GetHashCode()

作为默认哈希函数。Serves as the default hash function.

(Inherited from Object)
GetLifetimeService()

检索控制此实例的生存期策略的当前生存期服务对象。Retrieves the current lifetime service object that controls the lifetime policy for this instance.

(Inherited from MarshalByRefObject)
GetType()

获取当前实例的 TypeGets the Type of the current instance.

(Inherited from Object)
InitializeLifetimeService()

获取生存期服务对象来控制此实例的生存期策略。Obtains a lifetime service object to control the lifetime policy for this instance.

(Inherited from MarshalByRefObject)
MemberwiseClone()

创建当前 Object 的浅表副本。Creates a shallow copy of the current Object.

(Inherited from Object)
MemberwiseClone(Boolean)

创建当前 MarshalByRefObject 对象的浅表副本。Creates a shallow copy of the current MarshalByRefObject object.

(Inherited from MarshalByRefObject)
OpenExisting(String)

打开指定名称为信号量(如果已经存在)。Opens the specified named semaphore, if it already exists.

OpenExisting(String, SemaphoreRights)

用安全访问权限打开指定名称为信号量(如果已经存在)。Opens the specified named semaphore, if it already exists, with the desired security access.

Release()

退出信号量并返回前一个计数。Exits the semaphore and returns the previous count.

Release(Int32)

以指定的次数退出信号量并返回前一个计数。Exits the semaphore a specified number of times and returns the previous count.

SetAccessControl(SemaphoreSecurity)

设置已命名的系统信号量的访问控制安全性。Sets the access control security for a named system semaphore.

ToString()

返回表示当前对象的字符串。Returns a string that represents the current object.

(Inherited from Object)
TryOpenExisting(String, Semaphore)

打开指定名称为信号量(如果已经存在),并返回指示操作是否成功的值。Opens the specified named semaphore, if it already exists, and returns a value that indicates whether the operation succeeded.

TryOpenExisting(String, SemaphoreRights, Semaphore)

用安全访问权限打开指定名称为信号量(如果已经存在),并返回指示操作是否成功的值。Opens the specified named semaphore, if it already exists, with the desired security access, and returns a value that indicates whether the operation succeeded.

WaitOne()

阻止当前线程,直到当前 WaitHandle 收到信号。Blocks the current thread until the current WaitHandle receives a signal.

(Inherited from WaitHandle)
WaitOne(Int32)

阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)。Blocks the current thread until the current WaitHandle receives a signal, using a 32-bit signed integer to specify the time interval in milliseconds.

(Inherited from WaitHandle)
WaitOne(Int32, Boolean)

阻止当前线程,直到当前的 WaitHandle 收到信号为止,同时使用 32 位带符号整数指定时间间隔,并指定是否在等待之前退出同步域。Blocks the current thread until the current WaitHandle receives a signal, using a 32-bit signed integer to specify the time interval and specifying whether to exit the synchronization domain before the wait.

(Inherited from WaitHandle)
WaitOne(TimeSpan)

阻止当前线程,直到当前实例收到信号,同时使用 TimeSpan 指定时间间隔。Blocks the current thread until the current instance receives a signal, using a TimeSpan to specify the time interval.

(Inherited from WaitHandle)
WaitOne(TimeSpan, Boolean)

阻止当前线程,直到当前实例收到信号为止,同时使用 TimeSpan 指定时间间隔,并指定是否在等待之前退出同步域。Blocks the current thread until the current instance receives a signal, using a TimeSpan to specify the time interval and specifying whether to exit the synchronization domain before the wait.

(Inherited from WaitHandle)

Explicit Interface Implementations

IDisposable.Dispose()

释放 WaitHandle 使用的所有资源。Releases all resources used by the WaitHandle.

(Inherited from WaitHandle)

Extension Methods

GetAccessControl(Semaphore)

Returns the security descriptors for the specified semaphore.

SetAccessControl(Semaphore, SemaphoreSecurity)

Sets the security descriptors for the specified semaphore.

GetSafeWaitHandle(WaitHandle)

获取本机操作系统等待句柄的安全句柄。Gets the safe handle for a native operating system wait handle.

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

设置本机操作系统等待句柄的安全句柄。Sets a safe handle for a native operating system wait handle.

Applies to

Thread Safety

此类型是线程安全的。This type is thread safe.

See also