ReaderWriterLock ReaderWriterLock ReaderWriterLock ReaderWriterLock Class

定义

定义支持单个写线程和多个读线程的锁。Defines a lock that supports single writers and multiple readers.

public ref class ReaderWriterLock sealed : System::Runtime::ConstrainedExecution::CriticalFinalizerObject
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class ReaderWriterLock : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
type ReaderWriterLock = class
    inherit CriticalFinalizerObject
Public NotInheritable Class ReaderWriterLock
Inherits CriticalFinalizerObject
继承
ReaderWriterLockReaderWriterLockReaderWriterLockReaderWriterLock
属性

示例

下面的示例演示如何使用ReaderWriterLock保护共享资源(一个名为resource的整数值),该资源同时以多个线程的形式进行读取和写入。The following example demonstrates how to use a ReaderWriterLock to protect a shared resource, an integer value named resource, that is read concurrently and written exclusively by multiple threads. ReaderWriterLock请注意,在类级别声明,以便它对所有线程都可见。Note that the ReaderWriterLock is declared at the class level so that it is visible to all threads.

// 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;
   static Random^ rnd = gcnew Random;

   // Statistics.
   static int readerTimeouts = 0;
   static int writerTimeouts = 0;
   static int reads = 0;
   static int writes = 0;
   static void ThreadProc()
   {
      
      // 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( 50 );
         else
         if ( action < .90 )
                  UpgradeDowngrade( 100 );
         else
                  WriteToResource( 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( 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( 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( 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;
   static Random rnd = new Random();

   // 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(Convert.ToChar(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()
   {
      // 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(50);
         else if (action < .90)
            UpgradeDowngrade(100);
         else
            WriteToResource(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(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(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(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
   Private rnd As New Random()
   
   ' 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()
      ' 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(50)
         ElseIf action < 0.9 Then
            UpgradeDowngrade(100)
         Else
            WriteToResource(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(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(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(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.NET Framework 有下面两个读取器-编写器锁:ReaderWriterLockSlimReaderWriterLockThe .NET Framework.NET Framework has two reader-writer locks, ReaderWriterLockSlim and ReaderWriterLock. 建议对所有新开发的项目使用 ReaderWriterLockSlimReaderWriterLockSlim is recommended for all new development. 虽然 ReaderWriterLockSlim 类似于 ReaderWriterLock,但不同之处在于,前者简化了递归规则以及锁状态的升级和降级规则。ReaderWriterLockSlim is similar to ReaderWriterLock, but it has simplified rules for recursion and for upgrading and downgrading lock state. ReaderWriterLockSlim 避免了许多潜在的死锁情况。ReaderWriterLockSlim avoids many cases of potential deadlock. 另外,ReaderWriterLockSlim 的性能显著优于 ReaderWriterLockIn addition, the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock.

ReaderWriterLock用于同步对资源的访问。ReaderWriterLock is used to synchronize access to a resource. 在任何给定时间,它都允许对多个线程执行并发读取访问,或允许单个线程的写入访问。At any given time, it allows either concurrent read access for multiple threads, or write access for a single thread. 在资源更改不频繁的情况下,与简单ReaderWriterLock的一次性锁( Monitor例如)相比,提供更好的吞吐量。In a situation where a resource is changed infrequently, a ReaderWriterLock provides better throughput than a simple one-at-a-time lock, such as Monitor.

ReaderWriterLock在大多数访问都是读取的情况下最适合使用写入,而不是在短期内进行写入。ReaderWriterLock works best where most accesses are reads, while writes are infrequent and of short duration. 多个读取器将替换为单个编写器,这样就不会长时间阻止读取器和编写器。Multiple readers alternate with single writers, so that neither readers nor writers are blocked for long periods.

备注

长时间持有读取器锁或写入器锁将枯竭其他线程。Holding reader locks or writer locks for long periods will starve other threads. 为了获得最佳性能,请考虑重构应用程序以最大程度地缩短写入的持续时间。For best performance, consider restructuring your application to minimize the duration of writes.

线程可以持有读取器锁或写入器锁,但不能同时持有两者。A thread can hold a reader lock or a writer lock, but not both at the same time. 您可以使用UpgradeToWriterLockDowngradeFromWriterLock,而不是释放读取器锁以获取写线程锁。Instead of releasing a reader lock in order to acquire the writer lock, you can use UpgradeToWriterLock and DowngradeFromWriterLock.

递归锁请求增加了锁的锁计数。Recursive lock requests increase the lock count on a lock.

读取器和编写器分别排入队列。Readers and writers are queued separately. 当某个线程释放写入器锁时,在该时刻等待读取器队列中的所有线程都被授予读取器锁;所有这些读取器锁都已释放后,在编写器队列中等待的下一个线程(如果有)被授予写入器锁,依此类推。When a thread releases the writer lock, all threads waiting in the reader queue at that instant are granted reader locks; when all of those reader locks have been released, the next thread waiting in the writer queue, if any, is granted the writer lock, and so on. 换句话说, ReaderWriterLock在读取器集合和一个编写器之间交替。In other words, ReaderWriterLock alternates between a collection of readers, and one writer.

当编写器队列中的线程正在等待释放活动的读取器锁时,请求新读取器锁的线程将在读取器队列中累积。While a thread in the writer queue is waiting for active reader locks to be released, threads requesting new reader locks accumulate in the reader queue. 不会授予其请求,即使它们可能与现有读取器锁持有者共享并发访问;这有助于防止读者无限的读者堵塞写入器。Their requests are not granted, even though they could share concurrent access with existing reader-lock holders; this helps protect writers against indefinite blockage by readers.

获取对ReaderWriterLock接受超时值的锁的大多数方法。Most methods for acquiring locks on a ReaderWriterLock accept time-out values. 使用超时可避免应用程序中出现死锁。Use time-outs to avoid deadlocks in your application. 例如,线程可能会在一个资源上获取写线程锁,然后在第二个资源上请求读取器锁;同时,另一个线程可能会在第二个资源上获取写线程锁,并在第一个资源上请求读取器锁。For example, a thread might acquire the writer lock on one resource and then request a reader lock on a second resource; in the meantime, another thread might acquire the writer lock on the second resource, and request a reader lock on the first. 除非使用超时,否则线程会死锁。Unless time-outs are used, the threads deadlock.

如果超时间隔过期并且尚未授予锁请求,则方法会通过引发ApplicationException来将控件返回给调用线程。If the time-out interval expires and the lock request has not been granted, the method returns control to the calling thread by throwing an ApplicationException. 线程可以捕获此异常,并确定接下来要执行的操作。A thread can catch this exception and determine what action to take next.

超时以毫秒为单位。Time-outs are expressed in milliseconds. 如果使用System.TimeSpan指定超时值,则使用的值是表示TimeSpan的总毫秒数。If you use a System.TimeSpan to specify the time-out, the value used is the total number of whole milliseconds represented by the TimeSpan. 下表显示了有效的超时值(以毫秒为单位)。The following table shows the valid time-out values in milliseconds.

Value 说明Description
-1-1 线程会一直等待,直到获取锁,而不考虑它所需的时间。The thread waits until the lock is acquired, regardless of how long it takes. 对于指定整数超时的方法,可以使用常量InfiniteFor methods that specify integer time-outs, the constant Infinite can be used.
00 线程不等待获取锁。The thread does not wait to acquire the lock. 如果无法立即获取锁定,则该方法将返回。If the lock cannot be acquired immediately, the method returns.
>0>0 要等待的毫秒数。The number of milliseconds to wait.

但不允许使用负超时值(-1)。With the exception of -1, negative time-out values are not allowed. 如果指定一个非-1 的负整数,则改用超时值0。If you specify a negative integer other than -1, a time-out value of zero is used instead. (也就是说,如果无法立即获取锁定,则该方法将返回而不等待。)如果指定TimeSpan表示负- ArgumentOutOfRangeException 1 的负毫秒数的,则会引发。(That is, the method returns without waiting, if the lock cannot be acquired immediately.) If you specify a TimeSpan that represents a negative number of milliseconds other than -1, ArgumentOutOfRangeException is thrown.

构造函数

ReaderWriterLock() ReaderWriterLock() ReaderWriterLock() ReaderWriterLock()

初始化 ReaderWriterLock 类的新实例。Initializes a new instance of the ReaderWriterLock class.

属性

IsReaderLockHeld IsReaderLockHeld IsReaderLockHeld IsReaderLockHeld

获取一个值,该值指示当前线程是否持有读线程锁。Gets a value indicating whether the current thread holds a reader lock.

IsWriterLockHeld IsWriterLockHeld IsWriterLockHeld IsWriterLockHeld

获取一个值,该值指示当前线程是否持有写线程锁。Gets a value indicating whether the current thread holds the writer lock.

WriterSeqNum WriterSeqNum WriterSeqNum WriterSeqNum

获取当前序列号。Gets the current sequence number.

方法

AcquireReaderLock(Int32) AcquireReaderLock(Int32) AcquireReaderLock(Int32) AcquireReaderLock(Int32)

使用一个 Int32 超时值获取读线程锁。Acquires a reader lock, using an Int32 value for the time-out.

AcquireReaderLock(TimeSpan) AcquireReaderLock(TimeSpan) AcquireReaderLock(TimeSpan) AcquireReaderLock(TimeSpan)

使用一个 TimeSpan 超时值获取读线程锁。Acquires a reader lock, using a TimeSpan value for the time-out.

AcquireWriterLock(Int32) AcquireWriterLock(Int32) AcquireWriterLock(Int32) AcquireWriterLock(Int32)

使用一个 Int32 超时值获取写线程锁。Acquires the writer lock, using an Int32 value for the time-out.

AcquireWriterLock(TimeSpan) AcquireWriterLock(TimeSpan) AcquireWriterLock(TimeSpan) AcquireWriterLock(TimeSpan)

使用一个 TimeSpan 超时值获取写线程锁。Acquires the writer lock, using a TimeSpan value for the time-out.

AnyWritersSince(Int32) AnyWritersSince(Int32) AnyWritersSince(Int32) AnyWritersSince(Int32)

指示获取序列号之后是否已将写线程锁授予某个线程。Indicates whether the writer lock has been granted to any thread since the sequence number was obtained.

DowngradeFromWriterLock(LockCookie) DowngradeFromWriterLock(LockCookie) DowngradeFromWriterLock(LockCookie) DowngradeFromWriterLock(LockCookie)

将线程的锁状态还原为调用 UpgradeToWriterLock(Int32) 前的状态。Restores the lock status of the thread to what it was before UpgradeToWriterLock(Int32) was called.

Equals(Object) Equals(Object) Equals(Object) Equals(Object)

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

(Inherited from Object)
Finalize() Finalize() Finalize() Finalize()

确保垃圾回收器回收 ReaderWriterLock 对象时释放资源并执行其他清理操作。Ensures that resources are freed and other cleanup operations are performed when the garbage collector reclaims the ReaderWriterLock object.

GetHashCode() GetHashCode() GetHashCode() GetHashCode()

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

(Inherited from Object)
GetType() GetType() GetType() GetType()

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

(Inherited from Object)
MemberwiseClone() MemberwiseClone() MemberwiseClone() MemberwiseClone()

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

(Inherited from Object)
ReleaseLock() ReleaseLock() ReleaseLock() ReleaseLock()

释放锁,不管线程获取锁的次数如何。Releases the lock, regardless of the number of times the thread acquired the lock.

ReleaseReaderLock() ReleaseReaderLock() ReleaseReaderLock() ReleaseReaderLock()

减少锁计数。Decrements the lock count.

ReleaseWriterLock() ReleaseWriterLock() ReleaseWriterLock() ReleaseWriterLock()

减少写线程锁上的锁计数。Decrements the lock count on the writer lock.

RestoreLock(LockCookie) RestoreLock(LockCookie) RestoreLock(LockCookie) RestoreLock(LockCookie)

将线程的锁状态还原为调用 ReleaseLock() 前的状态。Restores the lock status of the thread to what it was before calling ReleaseLock().

ToString() ToString() ToString() ToString()

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

(Inherited from Object)
UpgradeToWriterLock(Int32) UpgradeToWriterLock(Int32) UpgradeToWriterLock(Int32) UpgradeToWriterLock(Int32)

使用一个 Int32 超时值将读线程锁升级为写线程锁。Upgrades a reader lock to the writer lock, using an Int32 value for the time-out.

UpgradeToWriterLock(TimeSpan) UpgradeToWriterLock(TimeSpan) UpgradeToWriterLock(TimeSpan) UpgradeToWriterLock(TimeSpan)

使用一个 TimeSpan 超时值将读线程锁升级为写线程锁。Upgrades a reader lock to the writer lock, using a TimeSpan value for the time-out.

适用于

线程安全性

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

另请参阅