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;
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 对象的引用的任何线程使用。 每个 Semaphore 对象都是单独的本地信号灯。

注意

默认情况下,命名信号灯不限于创建信号灯的用户。 其他用户可能能够打开和使用信号灯,包括通过多次获取信号灯而不释放信号灯来干扰信号灯。 若要限制对特定用户的访问,可以使用构造函数重载或在 SemaphoreAcl 创建命名信号量时传入 SemaphoreSecurity 。 避免在可能具有不受信任的用户运行代码的系统上使用命名信号灯,而不受访问限制。

构造函数

名称 说明
Semaphore(Int32, Int32, String, Boolean, SemaphoreSecurity)

初始化类的新实例 Semaphore ,指定初始条目数和最大并发条目数,(可选)指定系统信号灯对象的名称,指定一个变量,该值指示是否创建了新的系统信号灯,并指定系统信号灯的安全访问控制。

Semaphore(Int32, Int32, String, Boolean)

初始化类的新实例 Semaphore ,指定初始条目数和最大并发条目数,(可选)指定系统信号灯对象的名称,并指定一个变量,该值接收指示是否创建了新的系统信号灯的值。

Semaphore(Int32, Int32, String, NamedWaitHandleOptions, Boolean)

初始化类的新实例 Semaphore ,指定初始条目数和最大并发条目数,(可选)指定系统信号灯对象的名称和用于设置用户范围和会话范围访问的选项,并指定一个变量,用于接收指示是否创建了新的系统信号灯的值。

Semaphore(Int32, Int32, String, NamedWaitHandleOptions)

初始化类的新实例 Semaphore ,指定初始条目数和并发条目的最大数目,并选择性地指定系统信号灯对象的名称和用于设置用户范围和会话范围访问的选项。

Semaphore(Int32, Int32, String)

初始化类的新实例 Semaphore ,指定初始条目数和最大并发条目数,并选择性地指定系统信号灯对象的名称。

Semaphore(Int32, Int32)

初始化类的新实例 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, NamedWaitHandleOptions)

打开指定的命名信号灯(如果已存在)。 如果选项仅设置为当前用户,则为调用用户验证对象的访问控制。

OpenExisting(String, SemaphoreRights)

打开指定的命名信号灯(如果已存在),并具有所需的安全访问。

OpenExisting(String)

打开指定的命名信号灯(如果已存在)。

Release()

退出信号灯并返回以前的计数。

Release(Int32)

退出信号灯的指定次数并返回以前的计数。

SetAccessControl(SemaphoreSecurity)

设置命名系统信号灯的访问控制安全性。

ToString()

返回一个表示当前对象的字符串。

(继承自 Object)
TryOpenExisting(String, NamedWaitHandleOptions, Semaphore)

打开指定的命名信号量(如果已存在),并返回一个值,该值指示操作是否成功。 如果选项仅设置为当前用户,则为调用用户验证对象的访问控制。

TryOpenExisting(String, Semaphore)

打开指定的命名信号量(如果已存在),并返回一个值,该值指示操作是否成功。

TryOpenExisting(String, SemaphoreRights, Semaphore)

使用所需的安全访问打开指定的命名信号量(如果已存在),并返回一个值,该值指示操作是否成功。

WaitOne()

阻止当前线程,直到当前 WaitHandle 接收信号。

(继承自 WaitHandle)
WaitOne(Int32, Boolean)

阻止当前线程,直到当前 WaitHandle 接收信号,使用 32 位有符号整数指定时间间隔,并指定是否在等待之前退出同步域。

(继承自 WaitHandle)
WaitOne(Int32)

阻止当前线程,直到当前 WaitHandle 接收信号,使用 32 位有符号整数指定时间间隔(以毫秒为单位)。

(继承自 WaitHandle)
WaitOne(TimeSpan, Boolean)

阻止当前线程,直到当前实例收到信号,使用指定 TimeSpan 时间间隔并指定是否在等待之前退出同步域。

(继承自 WaitHandle)
WaitOne(TimeSpan)

阻止当前线程,直到当前实例收到信号,并使用 TimeSpan 指定时间间隔。

(继承自 WaitHandle)

显式接口实现

名称 说明
IDisposable.Dispose()

此 API 支持产品基础结构,不能在代码中直接使用。

释放该 WaitHandle命令使用的所有资源。

(继承自 WaitHandle)

扩展方法

名称 说明
GetAccessControl(Semaphore)

返回指定 semaphore的安全描述符。

GetSafeWaitHandle(WaitHandle)

获取本机操作系统等待句柄的安全句柄。

SetAccessControl(Semaphore, SemaphoreSecurity)

设置指定信号灯的安全描述符。

SetSafeWaitHandle(WaitHandle, SafeWaitHandle)

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

适用于

线程安全性

此类型是线程安全的。

另请参阅