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 不會對 或 Release 的呼叫 WaitOne 強制執行執行緒識別。 程式設計人員必須負責確保執行緒不會釋放號志太多次。 例如,假設某個號誌的最大計數為 2,且執行緒 A 和執行緒 B 都進入號誌。 若執行緒 B 中的程式設計錯誤導致呼叫 Release 兩次,則兩次呼叫都會成功。 此時號誌計數已滿,當執行緒 A 終於呼叫 Release 時,就會擲回 SemaphoreFullException

旗號有兩種類型:本機號志和具名系統號志。 如果您使用接受名稱的建構函式建立 Semaphore 物件,則會與該名稱的作業系統號志相關聯。 具名系統號志可在整個作業系統中看到,而且可用來同步處理常式的活動。 您可以建立多個 Semaphore 代表相同具名系統號志的物件,而且您可以使用 OpenExisting 方法來開啟現有的具名系統號志。

本機號志只存在於您的進程內。 在處理序內,只要是參考了本機 Semaphore 物件的執行緒,就可使用本機 Mutex。 每個 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
已淘汰.
已淘汰.

取得或設定原生 (Native) 的作業系統控制代碼。

(繼承來源 WaitHandle)
SafeWaitHandle

取得或設定原生 (Native) 的作業系統控制代碼。

(繼承來源 WaitHandle)

方法

Close()

釋放目前 WaitHandle 所持有的全部資源。

(繼承來源 WaitHandle)
CreateObjRef(Type)

建立包含所有相關資訊的物件,這些資訊是產生用來與遠端物件通訊的所需 Proxy。

(繼承來源 MarshalByRefObject)
Dispose()

釋放 WaitHandle 類別目前的執行個體所使用的全部資源。

(繼承來源 WaitHandle)
Dispose(Boolean)

當在衍生類別中覆寫時,釋放 WaitHandle 所使用的 Unmanaged 資源,並選擇性釋放 Managed 資源。

(繼承來源 WaitHandle)
Equals(Object)

判斷指定的物件是否等於目前的物件。

(繼承來源 Object)
GetAccessControl()

為具名系統號誌取得存取控制安全性。

GetHashCode()

做為預設雜湊函式。

(繼承來源 Object)
GetLifetimeService()
已淘汰.

擷取控制這個執行個體存留期 (Lifetime) 原則的目前存留期服務物件。

(繼承來源 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)

設定原生作業系統等候控制代碼的安全控制代碼。

適用於

執行緒安全性

此型別具備執行緒安全。

另請參閱