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,初始计数为零。 该示例启动五个线程,该线程阻止等待信号灯。 主线程使用 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调用时强制实施线程标识。 程序员有责任确保线程不会释放信号灯太多次。 例如,假定信号量的最大计数为 2 并且线程 A 和线程 B 都进入了该信号量。 如果线程 B 中的编程错误导致它两次成功调用了 Release。 信号灯计数已满,当线程 A 最终调用 Release 时,SemaphoreFullException 抛出。

信号灯有两种类型:本地信号灯和命名系统信号灯。 如果使用接受名称的构造函数创建 Semaphore 对象,则它与该名称的操作系统信号灯相关联。 命名系统信号灯在整个操作系统中可见,可用于同步进程的活动。 可以创建表示同一命名系统信号灯的多个 Semaphore 对象,并且可以使用 OpenExisting 该方法打开现有的命名系统信号灯。

本地信号灯仅存在于进程中。 进程中引用本地 Semaphore 对象的所有线程都可以使用本地 mutex。 每个 Semaphore 对象都是单独的本地信号灯。

构造函数

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)

设置本机操作系统等待句柄的安全句柄。

适用于

线程安全性

此类型是线程安全的。

另请参阅