ReaderWriterLockSlim 类

定义

表示用于管理资源访问的锁定状态,可实现多线程读取或进行独占式写入访问。

public ref class ReaderWriterLockSlim : IDisposable
public class ReaderWriterLockSlim : IDisposable
type ReaderWriterLockSlim = class
    interface IDisposable
Public Class ReaderWriterLockSlim
Implements IDisposable
继承
ReaderWriterLockSlim
实现

示例

以下示例演示一个简单的同步缓存,该缓存保存包含整数键的字符串。 的实例 ReaderWriterLockSlim 用于同步对 Dictionary<TKey,TValue> 充当内部缓存的 的访问。

该示例包括用于添加到缓存、从缓存中删除和从缓存中读取的简单方法。 为了演示超时,该示例包含一个方法,该方法仅在指定超时范围内可以添加到缓存中。

为了演示可升级模式,该示例包含一个方法,该方法检索与键关联的值,并将其与新值进行比较。 如果值未更改,该方法将返回一个状态,指示没有更改。 如果找不到键的值,则插入键/值对。 如果值已更改,则更新该值。 可升级模式允许线程根据需要从读取访问权限升级到写入访问权限,而不会有死锁的风险。

该示例包含一个嵌套枚举,该枚举指定演示可升级模式的方法的返回值。

该示例使用无参数构造函数创建锁,因此不允许递归。 当锁不允许递归时, ReaderWriterLockSlim 编程更简单,并且不容易出错。

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks
public class SynchronizedCache 
{
    private ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim();
    private Dictionary<int, string> innerCache = new Dictionary<int, string>();

    public int Count
    { get { return innerCache.Count; } }

    public string Read(int key)
    {
        cacheLock.EnterReadLock();
        try
        {
            return innerCache[key];
        }
        finally
        {
            cacheLock.ExitReadLock();
        }
    }

    public void Add(int key, string value)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Add(key, value);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

    public bool AddWithTimeout(int key, string value, int timeout)
    {
        if (cacheLock.TryEnterWriteLock(timeout))
        {
            try
            {
                innerCache.Add(key, value);
            }
            finally
            {
                cacheLock.ExitWriteLock();
            }
            return true;
        }
        else
        {
            return false;
        }
    }

    public AddOrUpdateStatus AddOrUpdate(int key, string value)
    {
        cacheLock.EnterUpgradeableReadLock();
        try
        {
            string result = null;
            if (innerCache.TryGetValue(key, out result))
            {
                if (result == value)
                {
                    return AddOrUpdateStatus.Unchanged;
                }
                else
                {
                    cacheLock.EnterWriteLock();
                    try
                    {
                        innerCache[key] = value;
                    }
                    finally
                    {
                        cacheLock.ExitWriteLock();
                    }
                    return AddOrUpdateStatus.Updated;
                }
            }
            else
            {
                cacheLock.EnterWriteLock();
                try
                {
                    innerCache.Add(key, value);
                }
                finally
                {
                    cacheLock.ExitWriteLock();
                }
                return AddOrUpdateStatus.Added;
            }
        }
        finally
        {
            cacheLock.ExitUpgradeableReadLock();
        }
    }

    public void Delete(int key)
    {
        cacheLock.EnterWriteLock();
        try
        {
            innerCache.Remove(key);
        }
        finally
        {
            cacheLock.ExitWriteLock();
        }
    }

    public enum AddOrUpdateStatus
    {
        Added,
        Updated,
        Unchanged
    };

    ~SynchronizedCache()
    {
       if (cacheLock != null) cacheLock.Dispose();
    }
}
Public Class SynchronizedCache
    Private cacheLock As New ReaderWriterLockSlim()
    Private innerCache As New Dictionary(Of Integer, String)

    Public ReadOnly Property Count As Integer
       Get
          Return innerCache.Count
       End Get
    End Property
    
    Public Function Read(ByVal key As Integer) As String
        cacheLock.EnterReadLock()
        Try
            Return innerCache(key)
        Finally
            cacheLock.ExitReadLock()
        End Try
    End Function

    Public Sub Add(ByVal key As Integer, ByVal value As String)
        cacheLock.EnterWriteLock()
        Try
            innerCache.Add(key, value)
        Finally
            cacheLock.ExitWriteLock()
        End Try
    End Sub

    Public Function AddWithTimeout(ByVal key As Integer, ByVal value As String, _
                                   ByVal timeout As Integer) As Boolean
        If cacheLock.TryEnterWriteLock(timeout) Then
            Try
                innerCache.Add(key, value)
            Finally
                cacheLock.ExitWriteLock()
            End Try
            Return True
        Else
            Return False
        End If
    End Function

    Public Function AddOrUpdate(ByVal key As Integer, _
                                ByVal value As String) As AddOrUpdateStatus
        cacheLock.EnterUpgradeableReadLock()
        Try
            Dim result As String = Nothing
            If innerCache.TryGetValue(key, result) Then
                If result = value Then
                    Return AddOrUpdateStatus.Unchanged
                Else
                    cacheLock.EnterWriteLock()
                    Try
                        innerCache.Item(key) = value
                    Finally
                        cacheLock.ExitWriteLock()
                    End Try
                    Return AddOrUpdateStatus.Updated
                End If
            Else
                cacheLock.EnterWriteLock()
                Try
                    innerCache.Add(key, value)
                Finally
                    cacheLock.ExitWriteLock()
                End Try
                Return AddOrUpdateStatus.Added
            End If
        Finally
            cacheLock.ExitUpgradeableReadLock()
        End Try
    End Function

    Public Sub Delete(ByVal key As Integer)
        cacheLock.EnterWriteLock()
        Try
            innerCache.Remove(key)
        Finally
            cacheLock.ExitWriteLock()
        End Try
    End Sub

    Public Enum AddOrUpdateStatus
        Added
        Updated
        Unchanged
    End Enum

    Protected Overrides Sub Finalize()
       If cacheLock IsNot Nothing Then cacheLock.Dispose()
    End Sub
End Class

然后, SynchronizedCache 以下代码使用 对象来存储蔬菜名称字典。 它创建三个任务。 第一个 将存储在数组 SynchronizedCache 中的蔬菜的名称写入实例。 第二个和第三个任务显示蔬菜的名称,第一个按升序 (从低索引到高索引) ,第二个按降序排列。 最后一个任务搜索字符串“cucumber”,并在找到它时调用 EnterUpgradeableReadLock 方法来替换字符串“绿豆”。

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
Imports System.Collections.Generic
Imports System.Threading
Imports System.Threading.Tasks
public class Example
{
   public static void Main()
   {
      var sc = new SynchronizedCache();
      var tasks = new List<Task>();
      int itemsWritten = 0;

      // Execute a writer.
      tasks.Add(Task.Run( () => { String[] vegetables = { "broccoli", "cauliflower",
                                                          "carrot", "sorrel", "baby turnip",
                                                          "beet", "brussel sprout",
                                                          "cabbage", "plantain",
                                                          "spinach", "grape leaves",
                                                          "lime leaves", "corn",
                                                          "radish", "cucumber",
                                                          "raddichio", "lima beans" };
                                  for (int ctr = 1; ctr <= vegetables.Length; ctr++)
                                     sc.Add(ctr, vegetables[ctr - 1]);

                                  itemsWritten = vegetables.Length;
                                  Console.WriteLine("Task {0} wrote {1} items\n",
                                                    Task.CurrentId, itemsWritten);
                                } ));
      // Execute two readers, one to read from first to last and the second from last to first.
      for (int ctr = 0; ctr <= 1; ctr++) {
         bool desc = ctr == 1;
         tasks.Add(Task.Run( () => { int start, last, step;
                                     int items;
                                     do {
                                        String output = String.Empty;
                                        items = sc.Count;
                                        if (! desc) {
                                           start = 1;
                                           step = 1;
                                           last = items;
                                        }
                                        else {
                                           start = items;
                                           step = -1;
                                           last = 1;
                                        }

                                        for (int index = start; desc ? index >= last : index <= last; index += step)
                                           output += String.Format("[{0}] ", sc.Read(index));

                                        Console.WriteLine("Task {0} read {1} items: {2}\n",
                                                          Task.CurrentId, items, output);
                                     } while (items < itemsWritten | itemsWritten == 0);
                             } ));
      }
      // Execute a red/update task.
      tasks.Add(Task.Run( () => { Thread.Sleep(100);
                                  for (int ctr = 1; ctr <= sc.Count; ctr++) {
                                     String value = sc.Read(ctr);
                                     if (value == "cucumber")
                                        if (sc.AddOrUpdate(ctr, "green bean") != SynchronizedCache.AddOrUpdateStatus.Unchanged)
                                           Console.WriteLine("Changed 'cucumber' to 'green bean'");
                                  }
                                } ));

      // Wait for all three tasks to complete.
      Task.WaitAll(tasks.ToArray());

      // Display the final contents of the cache.
      Console.WriteLine();
      Console.WriteLine("Values in synchronized cache: ");
      for (int ctr = 1; ctr <= sc.Count; ctr++)
         Console.WriteLine("   {0}: {1}", ctr, sc.Read(ctr));
   }
}
// The example displays the following output:
//    Task 1 read 0 items:
//
//    Task 3 wrote 17 items
//
//
//    Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
//    beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
//    s] [corn] [radish] [cucumber] [raddichio] [lima beans]
//
//    Task 2 read 0 items:
//
//    Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
//    leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
//    aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
//
//    Changed 'cucumber' to 'green bean'
//
//    Values in synchronized cache:
//       1: broccoli
//       2: cauliflower
//       3: carrot
//       4: sorrel
//       5: baby turnip
//       6: beet
//       7: brussel sprout
//       8: cabbage
//       9: plantain
//       10: spinach
//       11: grape leaves
//       12: lime leaves
//       13: corn
//       14: radish
//       15: green bean
//       16: raddichio
//       17: lima beans
Public Module Example
   Public Sub Main()
      Dim sc As New SynchronizedCache()
      Dim tasks As New List(Of Task)
      Dim itemsWritten As Integer
      
      ' Execute a writer.
      tasks.Add(Task.Run( Sub()
                             Dim vegetables() As String = { "broccoli", "cauliflower",
                                                            "carrot", "sorrel", "baby turnip",
                                                            "beet", "brussel sprout",
                                                            "cabbage", "plantain",
                                                            "spinach", "grape leaves",
                                                            "lime leaves", "corn",
                                                            "radish", "cucumber",
                                                            "raddichio", "lima beans" }
                             For ctr As Integer = 1 to vegetables.Length
                                sc.Add(ctr, vegetables(ctr - 1))
                             Next
                             itemsWritten = vegetables.Length
                             Console.WriteLine("Task {0} wrote {1} items{2}",
                                               Task.CurrentId, itemsWritten, vbCrLf)
                          End Sub))
      ' Execute two readers, one to read from first to last and the second from last to first.
      For ctr As Integer = 0 To 1
         Dim flag As Integer = ctr
         tasks.Add(Task.Run( Sub()
                                Dim start, last, stp As Integer
                                Dim items As Integer
                                Do
                                   Dim output As String = String.Empty
                                   items = sc.Count
                                   If flag = 0 Then
                                      start = 1 : stp = 1 : last = items
                                   Else
                                      start = items : stp = -1 : last = 1
                                   End If
                                   For index As Integer = start To last Step stp
                                      output += String.Format("[{0}] ", sc.Read(index))
                                   Next
                                   Console.WriteLine("Task {0} read {1} items: {2}{3}",
                                                           Task.CurrentId, items, output,
                                                           vbCrLf)
                                Loop While items < itemsWritten Or itemsWritten = 0
                             End Sub))
      Next
      ' Execute a red/update task.
      tasks.Add(Task.Run( Sub()
                             For ctr As Integer = 1 To sc.Count
                                Dim value As String = sc.Read(ctr)
                                If value = "cucumber" Then
                                   If sc.AddOrUpdate(ctr, "green bean") <> SynchronizedCache.AddOrUpdateStatus.Unchanged Then
                                      Console.WriteLine("Changed 'cucumber' to 'green bean'")
                                   End If
                                End If
                             Next
                          End Sub ))

      ' Wait for all three tasks to complete.
      Task.WaitAll(tasks.ToArray())

      ' Display the final contents of the cache.
      Console.WriteLine()
      Console.WriteLine("Values in synchronized cache: ")
      For ctr As Integer = 1 To sc.Count
         Console.WriteLine("   {0}: {1}", ctr, sc.Read(ctr))
      Next
   End Sub
End Module
' The example displays output like the following:
'    Task 1 read 0 items:
'
'    Task 3 wrote 17 items
'
'    Task 1 read 17 items: [broccoli] [cauliflower] [carrot] [sorrel] [baby turnip] [
'    beet] [brussel sprout] [cabbage] [plantain] [spinach] [grape leaves] [lime leave
'    s] [corn] [radish] [cucumber] [raddichio] [lima beans]
'
'    Task 2 read 0 items:
'
'    Task 2 read 17 items: [lima beans] [raddichio] [cucumber] [radish] [corn] [lime
'    leaves] [grape leaves] [spinach] [plantain] [cabbage] [brussel sprout] [beet] [b
'    aby turnip] [sorrel] [carrot] [cauliflower] [broccoli]
'
'    Changed 'cucumber' to 'green bean'
'
'    Values in synchronized cache:
'       1: broccoli
'       2: cauliflower
'       3: carrot
'       4: sorrel
'       5: baby turnip
'       6: beet
'       7: brussel sprout
'       8: cabbage
'       9: plantain
'       10: spinach
'       11: grape leaves
'       12: lime leaves
'       13: corn
'       14: radish
'       15: green bean
'       16: raddichio
'       17: lima beans

注解

使用 ReaderWriterLockSlim 保护由多个线程读取并一次由一个线程写入的资源。 ReaderWriterLockSlim 允许多个线程处于读取模式,允许一个线程处于具有锁独占所有权的写入模式,并允许具有读取访问权限的一个线程处于可升级读取模式,线程可以从该模式下升级到写入模式,而无需放弃对资源的读取访问权限。

注意

默认情况下,使用 标志创建 LockRecursionPolicy.NoRecursion 的新ReaderWriterLockSlim实例,不允许递归。 对于所有新开发,建议使用此默认策略,因为递归会导致不必要的复杂情况,并使代码更容易出现死锁。 若要简化从使用 MonitorReaderWriterLock的现有项目的迁移, LockRecursionPolicy.SupportsRecursion 可以使用 标志创建允许递归的 ReaderWriterLockSlim 实例。

线程可以在三种模式中进入锁:读取模式、写入模式和可升级读取模式。 (在本主题的其余部分,“可升级的读取模式”称为“可升级模式”,短语“enter x mode”优先于较长短语“进入锁定模式 x ”。)

无论递归策略如何,任何时候只能有一个线程处于写入模式。 当线程处于写入模式时,任何其他线程都不能在任何模式下进入锁。 任何时候只能有一个线程处于可升级模式。 任意数量的线程可以处于读取模式,并且可以有一个线程处于可升级模式,而其他线程则处于读取模式。

重要

此类型实现 IDisposable 接口。 在使用完类型后,您应直接或间接释放类型。 若要直接释放类型,请在 try/catch 块中调用其 Dispose 方法。 若要间接释放类型,请使用 using(在 C# 中)或 Using(在 Visual Basic 中)等语言构造。 有关详细信息,请参阅 IDisposable 接口主题中的“使用实现 IDisposable 的对象”一节。

ReaderWriterLockSlim 具有托管线程相关性;也就是说,每个 Thread 对象必须进行自己的方法调用才能进入和退出锁模式。 任何线程都不能更改另一个线程的模式。

ReaderWriterLockSlim如果 不允许递归,则尝试进入锁的线程可能会因为以下几个原因而阻塞:

  • 尝试进入读取模式的线程会阻止是否有线程等待进入写入模式,或者如果存在单个线程处于写入模式。

    注意

    在编写者排队时阻止新读者是一种有利于编写器的锁公平策略。 当前的公平政策平衡了读者和作者的公平性,以在最常见的方案中提高吞吐量。 .NET Framework的未来版本可能会引入新的公平政策。

  • 如果已有一个线程处于可升级模式、存在线程等待进入写入模式,或者如果存在单个线程处于写入模式,则尝试进入可升级模式的线程会阻止。

  • 尝试进入写入模式的线程会阻止这三种模式中的任何一种线程。

升级和降级锁

可升级模式适用于线程通常从受保护资源读取,但在满足某些条件时可能需要向其写入的情况。 在可升级模式下进入 ReaderWriterLockSlim 的线程对受保护资源具有读取访问权限,并且可以通过调用 EnterWriteLockTryEnterWriteLock 方法升级到写入模式。 由于一次只能有一个线程处于可升级模式,因此在不允许递归(这是默认策略)时,升级到写入模式不能死锁。

重要

无论递归策略如何,最初进入读取模式的线程都不允许升级到可升级模式或写入模式,因为该模式会造成死锁的概率很大。 例如,如果读取模式下的两个线程都尝试进入写入模式,它们将死锁。 可升级模式旨在避免此类死锁。

如果读取模式下有其他线程,则正在升级的线程会阻止。 当线程被阻止时,尝试进入读取模式的其他线程将被阻止。 当所有线程都退出读取模式时,被阻止的可升级线程将进入写入模式。 如果有其他线程等待进入写入模式,它们将保持阻止状态,因为处于可升级模式的单个线程会阻止它们获得对资源的独占访问权限。

当处于可升级模式的线程退出写入模式时,等待进入读取模式的其他线程可以这样做,除非有线程等待进入写入模式。 处于可升级模式的线程可以无限期升级和降级,只要它是写入受保护资源的唯一线程。

重要

如果允许多个线程进入写入模式或可升级模式,则不得允许一个线程独占可升级模式。 否则,尝试直接进入写入模式的线程将被无限期阻止,当它们被阻止时,其他线程将无法进入读取模式。

处于可升级模式的线程可以通过先调用 方法,然后调用 EnterReadLockExitUpgradeableReadLock 方法,降级到读取模式。 所有锁递归策略(甚至 NoRecursion)都允许使用此降级模式。

降级到读取模式后,线程在退出读取模式之前无法重新进入可升级模式。

以递归方式输入锁定

可以使用 ReaderWriterLockSlim 指定锁策略的构造函数并指定 来创建支持递归锁条目 ReaderWriterLockSlim(LockRecursionPolicy)LockRecursionPolicy.SupportsRecursion

注意

不建议对新开发使用递归,因为这会带来不必要的复杂情况,并使代码更容易出现死锁。

ReaderWriterLockSlim对于允许递归的 ,可以如下说明线程可以进入的模式:

  • 读取模式下的线程可以递归方式进入读取模式,但不能进入写入模式或可升级模式。 如果尝试执行此操作, LockRecursionException 则会引发 。 进入读取模式,然后进入写入模式或可升级模式是一种模式,其死锁概率很大,因此不允许这样做。 如前所述,为需要升级锁的情况提供了可升级模式。

  • 处于可升级模式的线程可以进入写入模式和/或读取模式,并且可以以递归方式进入这三种模式中的任何一种。 但是,如果读取模式下有其他线程,则尝试进入写入模式会阻止。

  • 写入模式下的线程可以进入读取模式和/或可升级模式,并且可以以递归方式进入这三种模式中的任何一种。

  • 尚未进入锁的线程可以进入任何模式。 此尝试可以阻止的原因与尝试进入非递归锁的原因相同。

只要线程退出每个模式的次数与进入该模式的次数完全相同,线程就可以以任何顺序退出其已进入的模式。 如果线程尝试退出某个模式的次数过多,或者退出它尚未进入的模式, SynchronizationLockException 则会引发 。

锁定状态

你可能会发现从锁的状态来看锁很有用。 可以 ReaderWriterLockSlim 处于以下四种状态之一:未进入、读取、升级和写入。

  • 未进入:在此状态下,没有线程进入锁 (或所有线程都退出锁定) 。

  • 读取:在此状态下,一个或多个线程已进入锁定,以便对受保护资源进行读取访问。

    注意

    线程可以使用 或 TryEnterReadLock 方法或从可升级模式EnterReadLock降级进入读取模式中的锁。

  • 升级:在此状态下,一个线程已进入用于读取访问权限的锁,并可以选择升级到写入访问权限 (即,处于可升级模式) ,并且零个或多个线程已进入锁定进行读取访问。 一次不能有一个线程进入具有升级选项的锁;尝试进入可升级模式的其他线程将被阻止。

  • 写入:在此状态下,一个线程已进入锁,以便对受保护资源进行写入访问。 该线程具有锁的独占所有权。 由于任何原因尝试进入锁的任何其他线程将被阻止。

下表描述了当线程 t 执行最左侧列中所述的操作时,对于不允许递归的锁,锁定状态之间的转换。 在它执行操作时, t 没有模式。 (表脚注中描述了处于可升级模式的特殊情况 t 。) 顶部行描述了锁的启动状态。 单元格描述线程发生的情况,并在括号中显示锁状态的更改。

未 (N) 输入 读取 (R) 升级 (U) 写入 (W)
t 进入读取模式 t 输入 (R) 。 t 如果线程正在等待写入模式,则阻止;否则, t 输入 。 t 如果线程正在等待写入模式,则阻止;否则, t 输入 。1 t 块。
t 进入可升级模式 t 输入 (U) 。 t 如果线程正在等待写入模式或升级模式,则阻止;否则, t 输入 (U) 。 t 块。 t 块。
t 进入写入模式 t 输入 (W) 。 t 块。 t 块。2 t 块。

1 如果在 t 可升级模式下启动,则进入读取模式。 此操作永远不会阻止。 锁定状态不会更改。 (然后,线程可以通过退出可升级模式来完成读取模式的降级。)

2 如果在 t 可升级模式下启动,它会阻止是否有处于读取模式的线程。 否则,它将升级到写入模式。 锁定状态更改为写入 (W) 。 如果 t 由于有线程处于读取模式而阻止,则只要最后一个线程退出读取模式,它就会立即进入写入模式,即使有线程正在等待进入写入模式。

当由于线程退出锁而发生状态更改时,将按如下所示选择要唤醒的下一个线程:

  • 首先,正在等待写入模式且已处于可升级模式的线程 (最多可以有一个此类线程) 。

  • 如果失败,则为正在等待写入模式的线程。

  • 如果失败,则为正在等待可升级模式的线程。

  • 否则,所有正在等待读取模式的线程。

在前两种情况下,锁定的后续状态始终为 Write (W) ,在第三种情况下,无论锁定的状态如何,在退出的线程触发状态更改时,始终为“升级” (U) 。 在最后一种情况下,如果状态更改后有线程处于可升级模式,则锁定状态为“升级 (U) ”;否则,无论之前的状态如何,“读取 (R) ”。

构造函数

ReaderWriterLockSlim()

使用默认属性值初始化 ReaderWriterLockSlim 类的新实例。

ReaderWriterLockSlim(LockRecursionPolicy)

在指定锁定递归策略的情况下初始化 ReaderWriterLockSlim 类的新实例。

属性

CurrentReadCount

获取已进入读取模式锁定状态的独有线程的总数。

IsReadLockHeld

获取一个值,该值指示当前线程是否已进入读取模式的锁定状态。

IsUpgradeableReadLockHeld

获取一个值,该值指示当前线程是否已进入可升级模式的锁定状态。

IsWriteLockHeld

获取一个值,该值指示当前线程是否已进入写入模式的锁定状态。

RecursionPolicy

获取一个值,该值指示当前 ReaderWriterLockSlim 对象的递归策略。

RecursiveReadCount

获取当前线程进入读取模式锁定状态的次数,用于指示递归。

RecursiveUpgradeCount

获取当前线程进入可升级模式锁定状态的次数,用于指示递归。

RecursiveWriteCount

获取当前线程进入写入模式锁定状态的次数,用于指示递归。

WaitingReadCount

获取等待进入读取模式锁定状态的线程总数。

WaitingUpgradeCount

获取等待进入可升级模式锁定状态的线程总数。

WaitingWriteCount

获取等待进入写入模式锁定状态的线程总数。

方法

Dispose()

释放 ReaderWriterLockSlim 类的当前实例所使用的所有资源。

EnterReadLock()

尝试进入读取模式锁定状态。

EnterUpgradeableReadLock()

尝试进入可升级模式锁定状态。

EnterWriteLock()

尝试进入写入模式锁定状态。

Equals(Object)

确定指定对象是否等于当前对象。

(继承自 Object)
ExitReadLock()

减少读取模式的递归计数,并在生成的计数为 0(零)时退出读取模式。

ExitUpgradeableReadLock()

减少可升级模式的递归计数,并在生成的计数为 0(零)时退出可升级模式。

ExitWriteLock()

减少写入模式的递归计数,并在生成的计数为 0(零)时退出写入模式。

GetHashCode()

作为默认哈希函数。

(继承自 Object)
GetType()

获取当前实例的 Type

(继承自 Object)
MemberwiseClone()

创建当前 Object 的浅表副本。

(继承自 Object)
ToString()

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

(继承自 Object)
TryEnterReadLock(Int32)

尝试进入读取模式锁定状态,可以选择整数超时时间。

TryEnterReadLock(TimeSpan)

尝试进入读取模式锁定状态,可以选择超时时间。

TryEnterUpgradeableReadLock(Int32)

尝试进入可升级模式锁定状态,可以选择超时时间。

TryEnterUpgradeableReadLock(TimeSpan)

尝试进入可升级模式锁定状态,可以选择超时时间。

TryEnterWriteLock(Int32)

尝试进入写入模式锁定状态,可以选择超时时间。

TryEnterWriteLock(TimeSpan)

尝试进入写入模式锁定状态,可以选择超时时间。

适用于

线程安全性

此类型是线程安全的。