ReaderWriterLock 類別
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
定義鎖定,它支援單一寫入器和多重讀取器。
public ref class ReaderWriterLock sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject
public ref class ReaderWriterLock sealed
public sealed class ReaderWriterLock : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
public sealed class ReaderWriterLock
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class ReaderWriterLock : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
type ReaderWriterLock = class
inherit CriticalFinalizerObject
type ReaderWriterLock = class
[<System.Runtime.InteropServices.ComVisible(true)>]
type ReaderWriterLock = class
inherit CriticalFinalizerObject
Public NotInheritable Class ReaderWriterLock
Inherits CriticalFinalizerObject
Public NotInheritable Class ReaderWriterLock
- 繼承
- 繼承
-
ReaderWriterLock
- 屬性
範例
下列範例示範如何使用 ReaderWriterLock 來保護共用資源、名為 resource
的整數值,由多個執行緒同時讀取和寫入。 請注意,會在類別層級宣告 , ReaderWriterLock 讓所有線程都能看見它。
// This example shows a ReaderWriterLock protecting a shared
// resource that is read concurrently and written exclusively
// by multiple threads.
// The complete code is located in the ReaderWriterLock
// class topic.
using namespace System;
using namespace System::Threading;
public ref class Test
{
public:
// Declaring the ReaderWriterLock at the class level
// makes it visible to all threads.
static ReaderWriterLock^ rwl = gcnew ReaderWriterLock;
// For this example, the shared resource protected by the
// ReaderWriterLock is just an integer.
static int resource = 0;
literal int numThreads = 26;
static bool running = true;
// Statistics.
static int readerTimeouts = 0;
static int writerTimeouts = 0;
static int reads = 0;
static int writes = 0;
static void ThreadProc()
{
Random^ rnd = gcnew Random;
// As long as a thread runs, it randomly selects
// various ways to read and write from the shared
// resource. Each of the methods demonstrates one
// or more features of ReaderWriterLock.
while ( running )
{
double action = rnd->NextDouble();
if ( action < .8 )
ReadFromResource( 10 );
else
if ( action < .81 )
ReleaseRestore( rnd, 50 );
else
if ( action < .90 )
UpgradeDowngrade( rnd, 100 );
else
WriteToResource( rnd, 100 );
}
}
// Shows how to request and release a reader lock, and
// how to handle time-outs.
static void ReadFromResource( int timeOut )
{
try
{
rwl->AcquireReaderLock( timeOut );
try
{
// It is safe for this thread to read from
// the shared resource.
Display( String::Format( "reads resource value {0}", resource ) );
Interlocked::Increment( reads );
}
finally
{
// Ensure that the lock is released.
rwl->ReleaseReaderLock();
}
}
catch ( ApplicationException^ )
{
// The reader lock request timed out.
Interlocked::Increment( readerTimeouts );
}
}
// Shows how to request and release the writer lock, and
// how to handle time-outs.
static void WriteToResource( Random^ rnd, int timeOut )
{
try
{
rwl->AcquireWriterLock( timeOut );
try
{
// It is safe for this thread to read or write
// from the shared resource.
resource = rnd->Next( 500 );
Display( String::Format( "writes resource value {0}", resource ) );
Interlocked::Increment( writes );
}
finally
{
// Ensure that the lock is released.
rwl->ReleaseWriterLock();
}
}
catch ( ApplicationException^ )
{
// The writer lock request timed out.
Interlocked::Increment( writerTimeouts );
}
}
// Shows how to request a reader lock, upgrade the
// reader lock to the writer lock, and downgrade to a
// reader lock again.
static void UpgradeDowngrade( Random^ rnd, int timeOut )
{
try
{
rwl->AcquireReaderLock( timeOut );
try
{
// It is safe for this thread to read from
// the shared resource.
Display( String::Format( "reads resource value {0}", resource ) );
Interlocked::Increment( reads );
// If it is necessary to write to the resource,
// you must either release the reader lock and
// then request the writer lock, or upgrade the
// reader lock. Note that upgrading the reader lock
// puts the thread in the write queue, behind any
// other threads that might be waiting for the
// writer lock.
try
{
LockCookie lc = rwl->UpgradeToWriterLock( timeOut );
try
{
// It is safe for this thread to read or write
// from the shared resource.
resource = rnd->Next( 500 );
Display( String::Format( "writes resource value {0}", resource ) );
Interlocked::Increment( writes );
}
finally
{
// Ensure that the lock is released.
rwl->DowngradeFromWriterLock( lc );
}
}
catch ( ApplicationException^ )
{
// The upgrade request timed out.
Interlocked::Increment( writerTimeouts );
}
// When the lock has been downgraded, it is
// still safe to read from the resource.
Display( String::Format( "reads resource value {0}", resource ) );
Interlocked::Increment( reads );
}
finally
{
// Ensure that the lock is released.
rwl->ReleaseReaderLock();
}
}
catch ( ApplicationException^ )
{
// The reader lock request timed out.
Interlocked::Increment( readerTimeouts );
}
}
// Shows how to release all locks and later restore
// the lock state. Shows how to use sequence numbers
// to determine whether another thread has obtained
// a writer lock since this thread last accessed the
// resource.
static void ReleaseRestore( Random^ rnd, int timeOut )
{
int lastWriter;
try
{
rwl->AcquireReaderLock( timeOut );
try
{
// It is safe for this thread to read from
// the shared resource. Cache the value. (You
// might do this if reading the resource is
// an expensive operation.)
int resourceValue = resource;
Display( String::Format( "reads resource value {0}", resourceValue ) );
Interlocked::Increment( reads );
// Save the current writer sequence number.
lastWriter = rwl->WriterSeqNum;
// Release the lock, and save a cookie so the
// lock can be restored later.
LockCookie lc = rwl->ReleaseLock();
// Wait for a random interval (up to a
// quarter of a second), and then restore
// the previous state of the lock. Note that
// there is no timeout on the Restore method.
Thread::Sleep( rnd->Next( 250 ) );
rwl->RestoreLock( lc );
// Check whether other threads obtained the
// writer lock in the interval. If not, then
// the cached value of the resource is still
// valid.
if ( rwl->AnyWritersSince( lastWriter ) )
{
resourceValue = resource;
Interlocked::Increment( reads );
Display( String::Format( "resource has changed {0}", resourceValue ) );
}
else
{
Display( String::Format( "resource has not changed {0}", resourceValue ) );
}
}
finally
{
// Ensure that the lock is released.
rwl->ReleaseReaderLock();
}
}
catch ( ApplicationException^ )
{
// The reader lock request timed out.
Interlocked::Increment( readerTimeouts );
}
}
// Helper method briefly displays the most recent
// thread action. Comment out calls to Display to
// get a better idea of throughput.
static void Display( String^ msg )
{
Console::Write( "Thread {0} {1}. \r", Thread::CurrentThread->Name, msg );
}
};
int main()
{
array<String^>^args = Environment::GetCommandLineArgs();
// Start a series of threads. Each thread randomly
// performs reads and writes on the shared resource.
array<Thread^>^t = gcnew array<Thread^>(Test::numThreads);
for ( int i = 0; i < Test::numThreads; i++ )
{
t[ i ] = gcnew Thread( gcnew ThreadStart( Test::ThreadProc ) );
t[ i ]->Name = gcnew String( Convert::ToChar( i + 65 ),1 );
t[ i ]->Start();
if ( i > 10 )
Thread::Sleep( 300 );
}
// Tell the threads to shut down, then wait until they all
// finish.
Test::running = false;
for ( int i = 0; i < Test::numThreads; i++ )
{
t[ i ]->Join();
}
// Display statistics.
Console::WriteLine( "\r\n {0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.", Test::reads, Test::writes, Test::readerTimeouts, Test::writerTimeouts );
Console::WriteLine( "Press ENTER to exit." );
Console::ReadLine();
return 0;
}
// The complete code is located in the ReaderWriterLock class topic.
using System;
using System.Threading;
public class Example
{
static ReaderWriterLock rwl = new ReaderWriterLock();
// Define the shared resource protected by the ReaderWriterLock.
static int resource = 0;
const int numThreads = 26;
static bool running = true;
// Statistics.
static int readerTimeouts = 0;
static int writerTimeouts = 0;
static int reads = 0;
static int writes = 0;
public static void Main()
{
// Start a series of threads to randomly read from and
// write to the shared resource.
Thread[] t = new Thread[numThreads];
for (int i = 0; i < numThreads; i++){
t[i] = new Thread(new ThreadStart(ThreadProc));
t[i].Name = new String((char)(i + 65), 1);
t[i].Start();
if (i > 10)
Thread.Sleep(300);
}
// Tell the threads to shut down and wait until they all finish.
running = false;
for (int i = 0; i < numThreads; i++)
t[i].Join();
// Display statistics.
Console.WriteLine("\n{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.",
reads, writes, readerTimeouts, writerTimeouts);
Console.Write("Press ENTER to exit... ");
Console.ReadLine();
}
static void ThreadProc()
{
Random rnd = new Random();
// Randomly select a way for the thread to read and write from the shared
// resource.
while (running) {
double action = rnd.NextDouble();
if (action < .8)
ReadFromResource(10);
else if (action < .81)
ReleaseRestore(rnd, 50);
else if (action < .90)
UpgradeDowngrade(rnd, 100);
else
WriteToResource(rnd, 100);
}
}
// Request and release a reader lock, and handle time-outs.
static void ReadFromResource(int timeOut)
{
try {
rwl.AcquireReaderLock(timeOut);
try {
// It is safe for this thread to read from the shared resource.
Display("reads resource value " + resource);
Interlocked.Increment(ref reads);
}
finally {
// Ensure that the lock is released.
rwl.ReleaseReaderLock();
}
}
catch (ApplicationException) {
// The reader lock request timed out.
Interlocked.Increment(ref readerTimeouts);
}
}
// Request and release the writer lock, and handle time-outs.
static void WriteToResource(Random rnd, int timeOut)
{
try {
rwl.AcquireWriterLock(timeOut);
try {
// It's safe for this thread to access from the shared resource.
resource = rnd.Next(500);
Display("writes resource value " + resource);
Interlocked.Increment(ref writes);
}
finally {
// Ensure that the lock is released.
rwl.ReleaseWriterLock();
}
}
catch (ApplicationException) {
// The writer lock request timed out.
Interlocked.Increment(ref writerTimeouts);
}
}
// Requests a reader lock, upgrades the reader lock to the writer
// lock, and downgrades it to a reader lock again.
static void UpgradeDowngrade(Random rnd, int timeOut)
{
try {
rwl.AcquireReaderLock(timeOut);
try {
// It's safe for this thread to read from the shared resource.
Display("reads resource value " + resource);
Interlocked.Increment(ref reads);
// To write to the resource, either release the reader lock and
// request the writer lock, or upgrade the reader lock. Upgrading
// the reader lock puts the thread in the write queue, behind any
// other threads that might be waiting for the writer lock.
try {
LockCookie lc = rwl.UpgradeToWriterLock(timeOut);
try {
// It's safe for this thread to read or write from the shared resource.
resource = rnd.Next(500);
Display("writes resource value " + resource);
Interlocked.Increment(ref writes);
}
finally {
// Ensure that the lock is released.
rwl.DowngradeFromWriterLock(ref lc);
}
}
catch (ApplicationException) {
// The upgrade request timed out.
Interlocked.Increment(ref writerTimeouts);
}
// If the lock was downgraded, it's still safe to read from the resource.
Display("reads resource value " + resource);
Interlocked.Increment(ref reads);
}
finally {
// Ensure that the lock is released.
rwl.ReleaseReaderLock();
}
}
catch (ApplicationException) {
// The reader lock request timed out.
Interlocked.Increment(ref readerTimeouts);
}
}
// Release all locks and later restores the lock state.
// Uses sequence numbers to determine whether another thread has
// obtained a writer lock since this thread last accessed the resource.
static void ReleaseRestore(Random rnd, int timeOut)
{
int lastWriter;
try {
rwl.AcquireReaderLock(timeOut);
try {
// It's safe for this thread to read from the shared resource,
// so read and cache the resource value.
int resourceValue = resource; // Cache the resource value.
Display("reads resource value " + resourceValue);
Interlocked.Increment(ref reads);
// Save the current writer sequence number.
lastWriter = rwl.WriterSeqNum;
// Release the lock and save a cookie so the lock can be restored later.
LockCookie lc = rwl.ReleaseLock();
// Wait for a random interval and then restore the previous state of the lock.
Thread.Sleep(rnd.Next(250));
rwl.RestoreLock(ref lc);
// Check whether other threads obtained the writer lock in the interval.
// If not, then the cached value of the resource is still valid.
if (rwl.AnyWritersSince(lastWriter)) {
resourceValue = resource;
Interlocked.Increment(ref reads);
Display("resource has changed " + resourceValue);
}
else {
Display("resource has not changed " + resourceValue);
}
}
finally {
// Ensure that the lock is released.
rwl.ReleaseReaderLock();
}
}
catch (ApplicationException) {
// The reader lock request timed out.
Interlocked.Increment(ref readerTimeouts);
}
}
// Helper method briefly displays the most recent thread action.
static void Display(string msg)
{
Console.Write("Thread {0} {1}. \r", Thread.CurrentThread.Name, msg);
}
}
' The complete code is located in the ReaderWriterLock class topic.
Imports System.Threading
Public Module Example
Private rwl As New ReaderWriterLock()
' Define the shared resource protected by the ReaderWriterLock.
Private resource As Integer = 0
Const numThreads As Integer = 26
Private running As Boolean = True
' Statistics.
Private readerTimeouts As Integer = 0
Private writerTimeouts As Integer = 0
Private reads As Integer = 0
Private writes As Integer = 0
Public Sub Main()
' Start a series of threads to randomly read from and
' write to the shared resource.
Dim t(numThreads - 1) As Thread
Dim i As Integer
For i = 0 To numThreads - 1
t(i) = New Thread(New ThreadStart(AddressOf ThreadProc))
t(i).Name = Chr(i + 65)
t(i).Start()
If i > 10 Then
Thread.Sleep(300)
End If
Next
' Tell the threads to shut down and wait until they all finish.
running = False
For i = 0 To numThreads - 1
t(i).Join()
Next
' Display statistics.
Console.WriteLine(vbCrLf & "{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.",
reads, writes, readerTimeouts, writerTimeouts)
Console.Write("Press ENTER to exit... ")
Console.ReadLine()
End Sub
Sub ThreadProc()
Dim rnd As New Random
' Randomly select a way for the thread to read and write from the shared
' resource.
While running
Dim action As Double = rnd.NextDouble()
If action < 0.8 Then
ReadFromResource(10)
ElseIf action < 0.81 Then
ReleaseRestore(rnd, 50)
ElseIf action < 0.9 Then
UpgradeDowngrade(rnd, 100)
Else
WriteToResource(rnd, 100)
End If
End While
End Sub
' Request and release a reader lock, and handle time-outs.
Sub ReadFromResource(timeOut As Integer)
Try
rwl.AcquireReaderLock(timeOut)
Try
' It's safe for this thread to read from the shared resource.
Display("reads resource value " & resource)
Interlocked.Increment(reads)
Finally
' Ensure that the lock is released.
rwl.ReleaseReaderLock()
End Try
Catch ex As ApplicationException
' The reader lock request timed out.
Interlocked.Increment(readerTimeouts)
End Try
End Sub
' Request and release the writer lock, and handle time-outs.
Sub WriteToResource(rnd As Random, timeOut As Integer)
Try
rwl.AcquireWriterLock(timeOut)
Try
' It's safe for this thread to read or write from the shared resource.
resource = rnd.Next(500)
Display("writes resource value " & resource)
Interlocked.Increment(writes)
Finally
' Ensure that the lock is released.
rwl.ReleaseWriterLock()
End Try
Catch ex As ApplicationException
' The writer lock request timed out.
Interlocked.Increment(writerTimeouts)
End Try
End Sub
' Requests a reader lock, upgrades the reader lock to the writer
' lock, and downgrades it to a reader lock again.
Sub UpgradeDowngrade(rnd As Random, timeOut As Integer)
Try
rwl.AcquireReaderLock(timeOut)
Try
' It's safe for this thread to read from the shared resource.
Display("reads resource value " & resource)
Interlocked.Increment(reads)
' To write to the resource, either release the reader lock and
' request the writer lock, or upgrade the reader lock. Upgrading
' the reader lock puts the thread in the write queue, behind any
' other threads that might be waiting for the writer lock.
Try
Dim lc As LockCookie = rwl.UpgradeToWriterLock(timeOut)
Try
' It's safe for this thread to read or write from the shared resource.
resource = rnd.Next(500)
Display("writes resource value " & resource)
Interlocked.Increment(writes)
Finally
' Ensure that the lock is released.
rwl.DowngradeFromWriterLock(lc)
End Try
Catch ex As ApplicationException
' The upgrade request timed out.
Interlocked.Increment(writerTimeouts)
End Try
' If the lock was downgraded, it's still safe to read from the resource.
Display("reads resource value " & resource)
Interlocked.Increment(reads)
Finally
' Ensure that the lock is released.
rwl.ReleaseReaderLock()
End Try
Catch ex As ApplicationException
' The reader lock request timed out.
Interlocked.Increment(readerTimeouts)
End Try
End Sub
' Release all locks and later restores the lock state.
' Uses sequence numbers to determine whether another thread has
' obtained a writer lock since this thread last accessed the resource.
Sub ReleaseRestore(rnd As Random ,timeOut As Integer)
Dim lastWriter As Integer
Try
rwl.AcquireReaderLock(timeOut)
Try
' It's safe for this thread to read from the shared resource,
' so read and cache the resource value.
Dim resourceValue As Integer = resource
Display("reads resource value " & resourceValue)
Interlocked.Increment(reads)
' Save the current writer sequence number.
lastWriter = rwl.WriterSeqNum
' Release the lock and save a cookie so the lock can be restored later.
Dim lc As LockCookie = rwl.ReleaseLock()
' Wait for a random interval and then restore the previous state of the lock.
Thread.Sleep(rnd.Next(250))
rwl.RestoreLock(lc)
' Check whether other threads obtained the writer lock in the interval.
' If not, then the cached value of the resource is still valid.
If rwl.AnyWritersSince(lastWriter) Then
resourceValue = resource
Interlocked.Increment(reads)
Display("resource has changed " & resourceValue)
Else
Display("resource has not changed " & resourceValue)
End If
Finally
' Ensure that the lock is released.
rwl.ReleaseReaderLock()
End Try
Catch ex As ApplicationException
' The reader lock request timed out.
Interlocked.Increment(readerTimeouts)
End Try
End Sub
' Helper method briefly displays the most recent thread action.
Sub Display(msg As String)
Console.Write("Thread {0} {1}. " & vbCr, Thread.CurrentThread.Name, msg)
End Sub
End Module
備註
重要
.NET Framework有兩個讀取器寫入器鎖定和 ReaderWriterLockSlimReaderWriterLock 。 建議針對所有新的開發使用 ReaderWriterLockSlim。 ReaderWriterLockSlim 類似於 ReaderWriterLock,但是它有遞迴以及升級和降級鎖定狀態的簡化規則。 ReaderWriterLockSlim 可避免可能發生死結的許多情況。 此外,ReaderWriterLockSlim 的效能明顯優於 ReaderWriterLock。
ReaderWriterLock 用來同步處理資源的存取。 在任何指定時間,它都會允許多個執行緒的並行讀取權限,或允許單一線程的寫入權限。 在資源不常變更的情況下,提供 ReaderWriterLock
比簡單的一次性鎖定更好的輸送量,例如 Monitor 。
ReaderWriterLock
最適合在讀取大部分的存取位置,而寫入不常且持續時間較短。 多個讀取器會替代單一寫入器,讓讀取器或寫入器不會長時間遭到封鎖。
注意
長時間保留讀取器鎖定或寫入器鎖定將會耗盡其他執行緒。 為了獲得最佳效能,請考慮重建您的應用程式,以將寫入持續時間降到最低。
執行緒可以保存讀取器鎖定或寫入器鎖定,但不能同時保存兩者。 您可以使用 UpgradeToWriterLock 和 DowngradeFromWriterLock ,而不是釋放讀取器鎖定來取得寫入器鎖定。
遞迴鎖定要求會增加鎖定的鎖定計數。
讀取器和寫入器會個別排入佇列。 當執行緒釋放寫入器鎖定時,該瞬間在讀取器佇列中等候的所有線程都會被授與讀取器鎖定;當所有讀取器鎖定都已釋放時,在寫入器佇列中等候的下一個執行緒,如果有的話,就會被授與寫入器鎖定等等。 換句話說, ReaderWriterLock
讀取器集合與一個寫入器之間的替代。
雖然寫入器佇列中的執行緒正在等候釋放作用中的讀取器鎖定,但要求新讀取器鎖定的執行緒會累積在讀取器佇列中。 即使其可以與現有的讀取器鎖定持有者共用平行存取權,也不會授與其要求;這有助於防止讀取器無限期封鎖寫入器。
取得接受逾時值鎖定 ReaderWriterLock
的大部分方法。 使用逾時來避免應用程式中的死結。 例如,執行緒可能會取得一個資源的寫入器鎖定,然後在第二個資源上要求讀取器鎖定;同時,另一個執行緒可能會取得第二個資源的寫入器鎖定,並在第一個資源上要求讀取器鎖定。 除非使用逾時,否則執行緒會死結。
如果逾時間隔過期,而且尚未授與鎖定要求,方法會擲 ApplicationException 回 ,以將控制權傳回給呼叫執行緒。 執行緒可以攔截此例外狀況,並判斷接下來要採取的動作。
逾時以毫碼錶示。 如果您使用 System.TimeSpan 來指定逾時,所使用的值就是 所 TimeSpan 表示的完整毫秒總數。 下表顯示以毫秒為單位的有效逾時值。
值 | 描述 |
---|---|
-1 | 執行緒會等到取得鎖定為止,而不論花費多少時間。 對於指定整數逾時的方法,可以使用常數 Infinite 。 |
0 | 執行緒不會等候取得鎖定。 如果無法立即取得鎖定,方法會傳回 。 |
>0 | 要等候的毫秒數。 |
除了 -1 之外,不允許負逾時值。 如果您指定 -1 以外的負整數,則會改用零的逾時值。 (也就是說,如果無法立即取得鎖定,則方法會傳回 ,) 如果您指定 TimeSpan 代表 -1 以外的負數毫秒數的 , ArgumentOutOfRangeException 則會擲回。
建構函式
ReaderWriterLock() |
初始化 ReaderWriterLock 類別的新執行個體。 |
屬性
IsReaderLockHeld |
取得值,指出目前的執行緒是否掌握讀取器的鎖定。 |
IsWriterLockHeld |
取得值,指出目前的執行緒是否掌握寫入器的鎖定。 |
WriterSeqNum |
取得目前的序號。 |
方法
AcquireReaderLock(Int32) |
使用逾時值 Int32 取得讀取器的鎖定。 |
AcquireReaderLock(TimeSpan) |
使用逾時值 TimeSpan 取得讀取器的鎖定。 |
AcquireWriterLock(Int32) |
使用逾時值 Int32 取得寫入器的鎖定。 |
AcquireWriterLock(TimeSpan) |
使用逾時值 TimeSpan 取得寫入器的鎖定。 |
AnyWritersSince(Int32) |
指示取得序號之後有無將寫入器鎖定授與至任何執行緒。 |
DowngradeFromWriterLock(LockCookie) |
將執行緒的鎖定狀態還原到呼叫 UpgradeToWriterLock(Int32) 之前的狀態。 |
Equals(Object) |
判斷指定的物件是否等於目前的物件。 (繼承來源 Object) |
Finalize() |
確認釋出資源,並在記憶體回收行程回收 ReaderWriterLock 物件時執行其他清除作業。 |
GetHashCode() |
做為預設雜湊函式。 (繼承來源 Object) |
GetType() |
取得目前執行個體的 Type。 (繼承來源 Object) |
MemberwiseClone() |
建立目前 Object 的淺層複製。 (繼承來源 Object) |
ReleaseLock() |
無論執行緒取得鎖定的次數為多少,都會釋放鎖定。 |
ReleaseReaderLock() |
減量鎖定計數。 |
ReleaseWriterLock() |
減量寫入器鎖定上的鎖定計數。 |
RestoreLock(LockCookie) |
將執行緒的鎖定狀態還原到呼叫 ReleaseLock() 之前的狀態。 |
ToString() |
傳回代表目前物件的字串。 (繼承來源 Object) |
UpgradeToWriterLock(Int32) |
使用逾時值 Int32,將讀取器鎖定升級至寫入器鎖定。 |
UpgradeToWriterLock(TimeSpan) |
使用逾時值 |
適用於
執行緒安全性
此型別具備執行緒安全。