ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim ReaderWriterLockSlim Class

정의

여러 스레드에서 읽을 수 있도록 허용하거나 쓰기를 위한 단독 액세스를 허용하여 리소스에 대한 액세스를 관리하는 데 사용되는 잠금을 나타냅니다.Represents a lock that is used to manage access to a resource, allowing multiple threads for reading or exclusive access for writing.

public ref class ReaderWriterLockSlim : IDisposable
public class ReaderWriterLockSlim : IDisposable
type ReaderWriterLockSlim = class
    interface IDisposable
Public Class ReaderWriterLockSlim
Implements IDisposable
상속
ReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlimReaderWriterLockSlim
구현

예제

다음 예제에서는 정수 키를 사용 하 여 문자열을 포함 하는 간단한 동기화 된 캐시를 보여 줍니다.The following example shows a simple synchronized cache that holds strings with integer keys. 인스턴스의 ReaderWriterLockSlim 에 대 한 액세스를 동기화 하는 데 사용 되는 Dictionary<TKey,TValue> 내부 캐시는 역할을 합니다.An instance of ReaderWriterLockSlim is used to synchronize access to the Dictionary<TKey,TValue> that serves as the inner cache.

이 예제에서는 간단한 방법, 캐시에 추가 하 고, 캐시에서 삭제 하 고, 캐시에서 읽기를 포함 합니다.The example includes simple methods to add to the cache, delete from the cache, and read from the cache. 제한 시간을 보여 주기 위해 예제에는 지정한 시간 제한 내에서 수행할 수 있는 경우에 캐시에 추가 하는 메서드가 포함 됩니다.To demonstrate time-outs, the example includes a method that adds to the cache only if it can do so within a specified time-out.

업그레이드 가능 모드를 보여 주기 위해 예제는 키와 연결 된 값을 검색 하는 메서드를 포함 하 고 새 값과 비교 합니다.To demonstrate upgradeable mode, the example includes a method that retrieves the value associated with a key and compares it with a new value. 값이 변경 된 경우 메서드는 변경 되지 않았음을 나타내는 상태를 반환 합니다.If the value is unchanged, the method returns a status indicating no change. 키에 대 한 값이 없는 없으면 키/값 쌍이 삽입 됩니다.If no value is found for the key, the key/value pair is inserted. 값을 변경 하는 경우 업데이트 됩니다.If the value has changed, it is updated. 업그레이드 가능 모드 스레드가 교착 상태는 위험 없이 필요에 따라 쓰기 액세스에 대 한 읽기 액세스를 업그레이드할 수 있습니다.Upgradeable mode allows the thread to upgrade from read access to write access as needed, without the risk of deadlocks.

이 예제에서는 업그레이드 가능 모드를 보여 주는 메서드의 반환 값을 지정 하는 중첩 된 열거형을 포함 합니다.The example includes a nested enumeration that specifies the return values for the method that demonstrates upgradeable mode.

이 예제에서는 매개 변수가 없는 생성자를 사용 하 여 잠금을 생성 하므로 재귀가 허용 되지 않습니다.The example uses the parameterless constructor to create the lock, so recursion is not allowed. 프로그래밍의 ReaderWriterLockSlim 잠금을 재귀를 허용 하지 않으면 더 간단 하 고 오류가 발생할 가능성이 감소 합니다.Programming the ReaderWriterLockSlim is simpler and less prone to error when the lock does not allow recursion.

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 vegetable 이름의 사전을 저장할 개체입니다.The following code then uses the SynchronizedCache object to store a dictionary of vegetable names. 세 가지 작업을 만듭니다.It creates three tasks. 첫 번째의 야채 그림을 배열에 저장 된 이름을 작성 한 SynchronizedCache 인스턴스.The first writes the names of vegetables stored in an array to a SynchronizedCache instance. 두 번째 및 세 번째 작업의 야채 그림 오름차순 (낮은 인덱스 높은 인덱스), 두 번째 내림차순 첫 번째 이름을 표시 합니다.The second and third task display the names of the vegetables, the first in ascending order (from low index to high index), the second in descending order. 마지막 작업 "cucumber" 문자열을 검색 하 고, 호출을 찾으면를 EnterUpgradeableReadLock "녹색 bean" 문자열을 대체 하는 방법입니다.The final task searches for the string "cucumber" and, when it finds it, calls the EnterUpgradeableReadLock method to substitute the string "green bean".

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 = Convert.ToBoolean(ctr);
         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 여러 스레드가 읽고 한 번에 하나의 스레드에 의해에 기록 하는 리소스를 보호 합니다.Use ReaderWriterLockSlim to protect a resource that is read by multiple threads and written to by one thread at a time. ReaderWriterLockSlim 여러 스레드에서 읽기 모드에 있을 수 있습니다, 그리고 스레드와 잠금을 단독 소유권을 사용 하 여 쓰기 모드에 있을 수 있고, 스레드 것을 포기 하지 않고도 쓰기 모드를 업그레이드할 수는 업그레이드 가능한 읽기 모드에 대 한 읽기 권한이 있는 스레드 하나 가는 리소스에 대 한 액세스를 읽습니다.ReaderWriterLockSlim allows multiple threads to be in read mode, allows one thread to be in write mode with exclusive ownership of the lock, and allows one thread that has read access to be in upgradeable read mode, from which the thread can upgrade to write mode without having to relinquish its read access to the resource.

참고

ReaderWriterLockSlimReaderWriterLock과 비슷하지만 재귀 및 잠금 상태 업그레이드/다운그레이드에 대한 간소화된 규칙을 포함합니다.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의 성능이 ReaderWriterLock보다 훨씬 더 놓습니다.In addition, the performance of ReaderWriterLockSlim is significantly better than ReaderWriterLock. ReaderWriterLockSlim은 모든 새 개발에 권장됩니다.ReaderWriterLockSlim is recommended for all new development.

기본적으로 새 인스턴스의 ReaderWriterLockSlim 사용 하 여 만들어진는 LockRecursionPolicy.NoRecursion 플래그 및 재귀를 허용 하지 않습니다.By default, new instances of ReaderWriterLockSlim are created with the LockRecursionPolicy.NoRecursion flag and do not allow recursion. 이 기본 정책은 재귀 불필요 한 복잡성을 소개 하 고 하면 코드를 교착 상태 발생 가능성이 있으므로 모든 새 개발에 권장 됩니다.This default policy is recommended for all new development, because recursion introduces unnecessary complications and makes your code more prone to deadlocks. 기존 마이그레이션을 간소화 하기 위해 사용 하는 프로젝트 Monitor 또는 ReaderWriterLock를 사용할 수 있습니다를 LockRecursionPolicy.SupportsRecursion 플래그의 인스턴스를 만들 ReaderWriterLockSlim 재귀 수 있도록 합니다.To simplify migration from existing projects that use Monitor or ReaderWriterLock, you can use the LockRecursionPolicy.SupportsRecursion flag to create instances of ReaderWriterLockSlim that allow recursion.

스레드 세 가지 모드로 잠금을 시작 수 있습니다: 모드를 읽고 쓰기 모드를 하 고 업그레이드 가능한 읽기 모드입니다.A thread can enter the lock in three modes: read mode, write mode, and upgradeable read mode. (이 항목의 나머지 부분에서는 "업그레이드 가능한 읽기 모드" 라고 "업그레이드 가능 모드"로 "입력 x 모드" 긴 구 보다 우선적으로 사용 하는 "에서 잠금에 진입 x 모드"입니다.)(In the rest of this topic, "upgradeable read mode" is referred to as "upgradeable mode", and the phrase "enter x mode" is used in preference to the longer phrase "enter the lock in x mode".)

재귀 정책에 관계 없이 언제 든 지 하나의 스레드만 쓰기 모드로 수 있습니다.Regardless of recursion policy, only one thread can be in write mode at any time. 스레드에서 쓰기 모드에 있으면 다른 스레드에서 모든 모드로 잠금을 시작할 수 있습니다.When a thread is in write mode, no other thread can enter the lock in any mode. 하나의 스레드는 언제 든 지 업그레이드 가능 모드로 수 있습니다.Only one thread can be in upgradeable mode at any time. 읽기 모드에서는 여러 스레드 수 되며 있을 수 있습니다 스레드와 업그레이드 가능 모드에서 다른 스레드가 읽기 모드 동안.Any number of threads can be in read mode, and there can be one thread in upgradeable mode while other threads are in read mode.

중요

이 형식이 구현 하는 IDisposable 인터페이스입니다.This type implements the IDisposable interface. 형식을 사용 하 여 마쳤으면 직접 또는 간접적으로의 삭제 해야 있습니다.When you have finished using the type, you should dispose of it either directly or indirectly. 직접 형식의 dispose 호출 해당 Dispose 의 메서드를 try / catch 블록입니다.To dispose of the type directly, call its Dispose method in a try/catch block. 삭제 하지 직접, 언어 구문 같은 사용 using (C#에서) 또는 Using (Visual Basic에서는).To dispose of it indirectly, use a language construct such as using (in C#) or Using (in Visual Basic). 자세한 내용은 "를 사용 하는 개체는 구현 IDisposable" 섹션을 참조 하세요.를 IDisposable 인터페이스 항목입니다.For more information, see the "Using an Object that Implements IDisposable" section in the IDisposable interface topic.

ReaderWriterLockSlim 에서는 관리 스레드 선호도 있습니다. 즉, 각 Thread 개체 자체 메서드 호출을 입력 하 고 잠금 모드를 종료 해야 합니다.ReaderWriterLockSlim has managed thread affinity; that is, each Thread object must make its own method calls to enter and exit lock modes. 스레드가 없습니다 다른 스레드의 모드를 변경할 수 있습니다.No thread can change the mode of another thread.

경우는 ReaderWriterLockSlim 재귀에서는 여러 가지 이유로 잠금을 시작 하려고 시도 차단할 수 있는 스레드를 허용 하지 않습니다.If a ReaderWriterLockSlim does not allow recursion, a thread that tries to enter the lock can block for several reasons:

  • 쓰기 모드 또는 쓰기 모드에는 단일 스레드 있는지 입력을 대기 중인 스레드가 없으면 읽기 모드 블록을 입력 하려고 하는 스레드입니다.A thread that tries to enter read mode blocks if there are threads waiting to enter write mode or if there is a single thread in write mode.

    참고

    새 판독기를 차단 하 여 대기 중인 경우는 기록기를 우선 하는 잠금 공정성 정책입니다.Blocking new readers when writers are queued is a lock fairness policy that favors writers. 현재의 관리 정책에는 공정성 가장 일반적인 시나리오에서 처리량을 높일 수는 판독기와 기록기를 분산 합니다.The current fairness policy balances fairness to readers and writers, to promote throughput in the most common scenarios. 이후 버전의 .NET Framework.NET Framework 새로운 관리 정책이 도입 될 수 있습니다.Future versions of the .NET Framework.NET Framework may introduce new fairness policies.

  • 이미 있으면 스레드에서 업그레이드 가능 모드로 쓰기 모드를 시작 하려고 대기 중인 스레드가 있는 경우 또는 쓰기 모드에는 단일 스레드 있으면 업그레이드 가능 모드 블록을 입력 하려고 하는 스레드입니다.A thread that tries to enter upgradeable mode blocks if there is already a thread in upgradeable mode, if there are threads waiting to enter write mode, or if there is a single thread in write mode.

  • 세 가지 모드 중 하나에서 스레드가 없는 경우 쓰기 모드 블록을 입력 하려고 하는 스레드입니다.A thread that tries to enter write mode blocks if there is a thread in any of the three modes.

업그레이드 / 다운 그레이드 잠금Upgrading and Downgrading Locks

업그레이드 가능 모드는 스레드가 일반적으로 보호 된 리소스에서 읽는 경우를 위한 일부 조건이 충족 될 경우 쓰기를 수행 해야 합니다.Upgradeable mode is intended for cases where a thread usually reads from the protected resource, but might need to write to it if some condition is met. 가 입력 한 스레드를 ReaderWriterLockSlim 업그레이드 가능 모드에 보호 된 리소스에 대 한 읽기 및 쓰기 모드를 호출 하 여 업그레이드할 수는 EnterWriteLock 또는 TryEnterWriteLock 메서드.A thread that has entered a ReaderWriterLockSlim in upgradeable mode has read access to the protected resource, and can upgrade to write mode by calling the EnterWriteLock or TryEnterWriteLock methods. 수 있기 때문에 하나의 스레드만 업그레이드 가능 모드에서 한 번에, 쓰기 모드를 업그레이드 없을 때 교착 상태에 기본 정책에는 재귀는 허용 되지 않습니다.Because there can be only one thread in upgradeable mode at a time, upgrading to write mode cannot deadlock when recursion is not allowed, which is the default policy.

중요

재귀 정책에 관계 없이 처음에 시작한 스레드는 해당 패턴은 교착 상태가 발생할 가능성이 매우 때문에 업그레이드 가능 모드 또는 쓰기 모드를로 업그레이드 모드가 허용 되지 않습니다 읽습니다.Regardless of recursion policy, a thread that initially entered read mode is not allowed to upgrade to upgradeable mode or write mode, because that pattern creates a strong probability of deadlocks. 예를 들어 입력 하려고 시도 하는 읽기 모드에 두 개의 스레드 모드를 작성 하는 경우 이러한 교착 상태가 됩니다.For example, if two threads in read mode both try to enter write mode, they will deadlock. 업그레이드 가능 모드는 이러한 교착 상태를 방지 하도록 설계 되었습니다.Upgradeable mode is designed to avoid such deadlocks.

읽기 모드에서는 요소를 업그레이드 하는 스레드가 다른 스레드가 없으면입니다.If there are other threads in read mode, the thread that is upgrading blocks. 스레드가 차단 되는 동안 읽기 모드를 시작 하려고 하는 다른 스레드가 차단 됩니다.While the thread is blocked, other threads that try to enter read mode are blocked. 읽기 모드에서 모든 스레드가 종료, 하는 경우 업그레이드 차단 된 스레드 쓰기 모드가 시작 됩니다.When all threads have exited from read mode, the blocked upgradeable thread enters write mode. 가 대기 중인 다른 스레드가 쓰기 모드 상태로 유지 됩니다 차단 업그레이드 가능 모드에 있는 단일 스레드가 리소스에 단독으로 액세스 하지 못하도록 방지 합니다.If there are other threads waiting to enter write mode, they remain blocked, because the single thread that is in upgradeable mode prevents them from gaining exclusive access to the resource.

쓰기 모드를 종료 하는 업그레이드 가능 모드에서 스레드를 대기 중인 스레드가 쓰기 모드 없는 따라서 읽기 모드를 시작 하려고 대기 중인 다른 스레드가 가능 합니다.When the thread in upgradeable mode exits write mode, other threads that are waiting to enter read mode can do so, unless there are threads waiting to enter write mode. 스레드에서 업그레이드 가능 모드로 업그레이드 하 고 해당 스레드를 보호 된 리소스에 쓰는 것으로 무기한으로 다운 그레이드할 수 있습니다.The thread in upgradeable mode can upgrade and downgrade indefinitely, as long as it is the only thread that writes to the protected resource.

중요

입력에 여러 스레드를 허용 하는 경우 쓰기 모드 또는 가능 모드가 시작 되었으면 스레드와 업그레이드 가능 모드를 독점할 수 없도록 해야 합니다.If you allow multiple threads to enter write mode or upgradeable mode, you must not allow one thread to monopolize upgradeable mode. 이 고, 그렇지 입력 하려고 하는 스레드 작성 모드 직접 차단 됩니다 무기한으로 차단 되는 동안 다른 스레드가 없게 됩니다 읽기 모드를 시작 합니다.Otherwise, threads that try to enter write mode directly will be blocked indefinitely, and while they are blocked, other threads will be unable to enter read mode.

스레드에서 업그레이드 가능 모드에서 첫 번째 호출 하 여 읽기 모드로 다운 그레이드할 수는 EnterReadLock 메서드를 호출한 다음는 ExitUpgradeableReadLock 메서드.A thread in upgradeable mode can downgrade to read mode by first calling the EnterReadLock method and then calling the ExitUpgradeableReadLock method. 이 다운 그레이드 패턴 모든 잠금 재귀 정책에 허용 NoRecursion합니다.This downgrade pattern is allowed for all lock recursion policies, even NoRecursion.

읽기 모드도 다운 그레이드 스레드를 다시 시작 가능 모드가 시작 되었으면 읽기 모드를 종료 해야 합니다.After downgrading to read mode, a thread cannot reenter upgradeable mode until it has exited from read mode.

잠금을 재귀적으로 입력합니다.Entering the Lock Recursively

만들 수 있습니다는 ReaderWriterLockSlim 를 사용 하 여 재귀 잠금 항목을 지는 ReaderWriterLockSlim(LockRecursionPolicy) 잠금 정책과 지정 지정 하는 생성자 LockRecursionPolicy.SupportsRecursion합니다.You can create a ReaderWriterLockSlim that supports recursive lock entry by using the ReaderWriterLockSlim(LockRecursionPolicy) constructor that specifies lock policy, and specifying LockRecursionPolicy.SupportsRecursion.

참고

재귀를 사용 하 여 불필요 한 복잡성을 소개 하 고 하면 코드를 교착 상태 발생 가능성이 있기 때문에 새로운 개발에 권장 되지 않습니다.The use of recursion is not recommended for new development, because it introduces unnecessary complications and makes your code more prone to deadlocks.

에 대 한는 ReaderWriterLockSlim 재귀를 허용 하는 스레드를 입력할 수 모드에 대 한 다음 한다고 할 수 있습니다.For a ReaderWriterLockSlim that allows recursion, the following can be said about the modes a thread can enter:

  • 읽기 모드에 있는 스레드에서 읽기 모드를 재귀적으로 입력할 수 있지만 쓰기 모드 또는 업그레이드 가능 모드를 입력할 수 없습니다.A thread in read mode can enter read mode recursively, but cannot enter write mode or upgradeable mode. 이 작업을 수행 하려는 경우는 LockRecursionException throw 됩니다.If it tries to do this, a LockRecursionException is thrown. 입력 읽거나 모드와 입력 한 다음 쓰기 모드 업그레이드 가능 모드 이므로 강력한 교착 상태 확률이 패턴을 사용할 수 없습니다.Entering read mode and then entering write mode or upgradeable mode is a pattern with a strong probability of deadlocks, so it is not allowed. 앞에서 설명한 대로 업그레이드 가능 모드로 잠금을 업그레이드 해야 하는 경우 제공 됩니다.As discussed earlier, upgradeable mode is provided for cases where it is necessary to upgrade a lock.

  • 업그레이드 가능 모드로 스레드에서 쓰기 모드 및/또는 읽기 모드를 입력할 수 있고, 세 가지 모드 재귀적으로 입력할 수 있습니다.A thread in upgradeable mode can enter write mode and/or read mode, and can enter any of the three modes recursively. 그러나 시작 하려는 시도가 다른 스레드에서 읽기 모드에 있는 경우 쓰기 모드 차단 합니다.However, an attempt to enter write mode blocks if there are other threads in read mode.

  • 쓰기 모드로 스레드에서 읽기 모드 및/또는 업그레이드 가능 모드를 입력할 수 있고, 세 가지 모드 재귀적으로 입력할 수 있습니다.A thread in write mode can enter read mode and/or upgradeable mode, and can enter any of the three modes recursively.

  • 스레드 잠금을 시작 하지는 모든 모드를 입력할 수 있습니다.A thread that has not entered the lock can enter any mode. 비재귀적 잠금에 진입 하려고와 같은 이유로이 시도 차단할 수 있습니다.This attempt can block for the same reasons as an attempt to enter a non-recursive lock.

스레드 모드가 해당 횟수 만큼 정확 하 게 각 모드를 종료 하는 것으로 순서에 관계 없이 입력이 모드를 종료할 수 있습니다.A thread can exit the modes it has entered in any order, as long as it exits each mode exactly as many times as it entered that mode. 스레드 시작 하지 않았으면 모드를 종료 하거나 종료 모드를 너무 많이 시도 하는 경우는 SynchronizationLockException throw 됩니다.If a thread tries to exit a mode too many times, or to exit a mode it has not entered, a SynchronizationLockException is thrown.

잠금 상태Lock States

잠금의 상태 측면에서 생각 하는 것이 유용할 수 있습니다.You may find it useful to think of the lock in terms of its states. ReaderWriterLockSlim 네 가지 상태 중 하나일 수 있습니다: 업그레이드를 입력 하지 읽기 및 쓰기입니다.A ReaderWriterLockSlim can be in one of four states: not entered, read, upgrade, and write.

  • 입력 하지 않음: 이 상태에서는 잠금을 시작한 스레드가 없거나 모든 스레드가 잠금을 종료 했습니다.Not entered: In this state, no threads have entered the lock (or all threads have exited the lock).

  • 읽음 이 상태에서 하나 이상의 스레드는 보호 된 리소스에 대 한 읽기 액세스 권한을 잠금으로 입력 했습니다.Read: In this state, one or more threads have entered the lock for read access to the protected resource.

    참고

    스레드를 사용 하 여 읽기 모드로 잠금을 입력할 수는 EnterReadLock 또는 TryEnterReadLock 메서드 또는 업그레이드 가능 모드에서 다운 그레이드 하 여 합니다.A thread can enter the lock in read mode by using the EnterReadLock or TryEnterReadLock methods, or by downgrading from upgradeable mode.

  • 업그레이드할 이 상태에서 한 스레드는 읽기 액세스를 위해 잠금을 시작 하 고 (즉, 업그레이드 가능 모드에서) 쓰기 권한으로 업그레이드 하는 옵션을 사용 하 고, 0 개 이상의 스레드에서 읽기 액세스 잠금을 시작 했습니다.Upgrade: In this state, one thread has entered the lock for read access with the option to upgrade to write access (that is, in upgradeable mode), and zero or more threads have entered the lock for read access. 한 번에 둘 이상의 스레드가; 업그레이드 하는 옵션을 사용 하 여 잠금을 입력할 수 있습니다. 업그레이드 가능 모드를 시작 하려고 하는 추가 스레드가 차단 됩니다.No more than one thread at a time can enter the lock with the option to upgrade; additional threads that try to enter upgradeable mode are blocked.

  • 기록 이 상태에서 한 스레드는 보호 된 리소스에 대 한 쓰기 액세스 권한을 잠금으로 입력 했습니다.Write: In this state, one thread has entered the lock for write access to the protected resource. 해당 스레드가 단독으로 잠금 소유 합니다.That thread has exclusive possession of the lock. 어떤 이유로 잠금에 진입 하려고 하는 다른 스레드가 차단 됩니다.Any other thread that tries to enter the lock for any reason is blocked.

다음 표에서 재귀 때 스레드를 허용 하지 않는 잠금에 대 한 잠금 상태 전환을 t 맨 왼쪽 열에 설명 된 작업을 수행 합니다.The following table describes the transitions between lock states, for locks that do not allow recursion, when a thread t takes the action described in the leftmost column. 작업에 걸리는 시간에 t 모드가 없습니다.At the time it takes the action, t has no mode. (특별 한 경우 여기서 t 중인 업그레이드 가능 모드 표의 각주에 설명 되어 있습니다.) 맨 위 행 잠금의 시작 상태를 설명합니다.(The special case where t is in upgradeable mode is described in the table footnotes.) The top row describes the starting state of the lock. 셀에는 잠금 상태 변경에 괄호 안에 표시 및 스레드 되나요 설명 합니다.The cells describe what happens to the thread, and show changes to the lock state in parentheses.

입력된 되지 않습니다 (N)Not entered (N) Read (R)Read (R) 업그레이드 (U)Upgrade (U) 쓰기 (W)Write (W)
t 읽기 모드로 전환t enters read mode t (R)을 입력합니다.t enters (R). t 블록 스레드에서 쓰기 모드에 대 한 대기 중인 경우 그렇지 않으면 t 입력 합니다.t blocks if threads are waiting for write mode; otherwise, t enters. t 블록 스레드에서 쓰기 모드에 대 한 대기 중인 경우 그렇지 않으면 t 를 입력 합니다. 1t blocks if threads are waiting for write mode; otherwise, t enters.1 t 차단 합니다.t blocks.
t 업그레이드 가능 모드가 시작t enters upgradeable mode t (U)을 입력합니다.t enters (U). t 스레드가 서로 대기 하는 경우 블록 쓰기 모드 또는 업그레이드 모드 그렇지 않으면 t (U)을 입력 합니다.t blocks if threads are waiting for write mode or upgrade mode; otherwise, t enters (U). t 차단 합니다.t blocks. t 차단 합니다.t blocks.
t 쓰기 모드로 전환t enters write mode t 입력 (W).t enters (W). t 차단 합니다.t blocks. t 차단 합니다. 2t blocks.2 t 차단 합니다.t blocks.

1 경우 t 시작 축소 가능 모드에서 읽기 모드가 있습니다.1 If t starts out in upgradeable mode, it enters read mode. 이 작업을 하지 차단합니다.This action never blocks. 잠금 상태를 변경 하지 않습니다.The lock state does not change. (스레드에서 업그레이드 가능 모드를 종료 하 여 읽기 모드로 다운 그레이드를 완료할 수 있습니다.)(The thread can then complete a downgrade to read mode by exiting upgradeable mode.)

2 경우 t 읽기 모드로 스레드가 있으면 차단 업그레이드 가능 모드로 시작 합니다.2 If t starts out in upgradeable mode, it blocks if there are threads in read mode. 그렇지 않으면 쓰기 모드를 업그레이드 합니다.Otherwise it upgrades to write mode. 잠금 상태 변경에 쓰기 (W).The lock state changes to Write (W). 경우 t 읽기 모드로 중인 스레드가 있으므로 차단 마지막 스레드에서 읽기 모드를 종료 하는 즉시 쓰기 모드가 시작, 경우에 대기 중인 스레드가 쓰기 모드입니다.If t blocks because there are threads in read mode, it enters write mode as soon as the last thread exits read mode, even if there are threads waiting to enter write mode.

상태 변경이 발생 하는 스레드가 잠금을 종료 때문에 설정을 선택 해제 하는 다음 스레드에서 다음과 같이 선택 됩니다.When a state change occurs because a thread exits the lock, the next thread to be awakened is selected as follows:

  • 먼저 대기 중인 스레드가 쓰기 모드 및 이미 업그레이드 가능 모드 (있을 수 있습니다 최대 이러한 스레드와).First, a thread that is waiting for write mode and is already in upgradeable mode (there can be at most one such thread).

  • 쓰기 모드에 대 한 대기 중인 스레드가 실패 합니다.Failing that, a thread that is waiting for write mode.

  • 업그레이드 가능 모드에 대 한 대기 중인 스레드가 실패 합니다.Failing that, a thread that is waiting for upgradeable mode.

  • 읽기 모드에 대 한 대기 중인 모든 스레드는 실패 합니다.Failing that, all threads that are waiting for read mode.

후속 잠금 상태가 항상 쓰기 (W)는 첫 번째 두 사례와 업그레이드 (U) 세 번째 경우 기존 스레드는 상태 변경이 트리거될 때 잠금 상태에 관계 없이 합니다.The subsequent state of the lock is always Write (W) in the first two cases and Upgrade (U) in the third case, regardless of the state of the lock when the exiting thread triggered the state change. 마지막 경우에서 잠금 상태 업그레이드 (U) 없는 경우은 스레드에서 업그레이드 가능 모드로 Read (R) 상태 변경 후이 고, 그렇지 이전 상태에 관계 없이 합니다.In the last case, the state of the lock is Upgrade (U) if there is a thread in upgradeable mode after the state change, and Read (R) otherwise, regardless of the prior state.

생성자

ReaderWriterLockSlim() ReaderWriterLockSlim() ReaderWriterLockSlim() ReaderWriterLockSlim()

기본 속성 값으로 ReaderWriterLockSlim 클래스의 새 인스턴스를 초기화합니다.Initializes a new instance of the ReaderWriterLockSlim class with default property values.

ReaderWriterLockSlim(LockRecursionPolicy) ReaderWriterLockSlim(LockRecursionPolicy) ReaderWriterLockSlim(LockRecursionPolicy) ReaderWriterLockSlim(LockRecursionPolicy)

잠금 재귀 정책을 지정하여 ReaderWriterLockSlim 클래스의 새 인스턴스를 초기화합니다.Initializes a new instance of the ReaderWriterLockSlim class, specifying the lock recursion policy.

속성

CurrentReadCount CurrentReadCount CurrentReadCount CurrentReadCount

읽기 모드로 잠금을 시작한 고유 스레드의 총 개수를 가져옵니다.Gets the total number of unique threads that have entered the lock in read mode.

IsReadLockHeld IsReadLockHeld IsReadLockHeld IsReadLockHeld

현재 스레드에서 읽기 모드로 잠금을 시작했는지 여부를 나타내는 값을 가져옵니다.Gets a value that indicates whether the current thread has entered the lock in read mode.

IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld IsUpgradeableReadLockHeld

현재 스레드에서 업그레이드 가능 모드로 잠금을 시작했는지 여부를 나타내는 값을 가져옵니다.Gets a value that indicates whether the current thread has entered the lock in upgradeable mode.

IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld IsWriteLockHeld

현재 스레드에서 쓰기 모드로 잠금을 시작했는지 여부를 나타내는 값을 가져옵니다.Gets a value that indicates whether the current thread has entered the lock in write mode.

RecursionPolicy RecursionPolicy RecursionPolicy RecursionPolicy

현재 ReaderWriterLockSlim 개체에 대한 재귀 정책을 나타내는 값을 가져옵니다.Gets a value that indicates the recursion policy for the current ReaderWriterLockSlim object.

RecursiveReadCount RecursiveReadCount RecursiveReadCount RecursiveReadCount

재귀를 확인하기 위해 현재 스레드에서 읽기 모드로 잠금을 시작한 횟수를 가져옵니다.Gets the number of times the current thread has entered the lock in read mode, as an indication of recursion.

RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount RecursiveUpgradeCount

재귀를 확인하기 위해 현재 스레드에서 업그레이드 가능 모드로 잠금을 시작한 횟수를 가져옵니다.Gets the number of times the current thread has entered the lock in upgradeable mode, as an indication of recursion.

RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount RecursiveWriteCount

재귀를 확인하기 위해 현재 스레드에서 쓰기 모드로 잠금을 시작한 횟수를 가져옵니다.Gets the number of times the current thread has entered the lock in write mode, as an indication of recursion.

WaitingReadCount WaitingReadCount WaitingReadCount WaitingReadCount

읽기 모드로 잠금을 시작하려고 대기 중인 스레드의 총 개수를 가져옵니다.Gets the total number of threads that are waiting to enter the lock in read mode.

WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount WaitingUpgradeCount

업그레이드 가능 모드로 잠금을 시작하려고 대기 중인 스레드의 총 개수를 가져옵니다.Gets the total number of threads that are waiting to enter the lock in upgradeable mode.

WaitingWriteCount WaitingWriteCount WaitingWriteCount WaitingWriteCount

쓰기 모드로 잠금을 시작하려고 대기 중인 스레드의 총 개수를 가져옵니다.Gets the total number of threads that are waiting to enter the lock in write mode.

메서드

Dispose() Dispose() Dispose() Dispose()

ReaderWriterLockSlim 클래스의 현재 인스턴스에서 사용하는 모든 리소스를 해제합니다.Releases all resources used by the current instance of the ReaderWriterLockSlim class.

EnterReadLock() EnterReadLock() EnterReadLock() EnterReadLock()

읽기 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in read mode.

EnterUpgradeableReadLock() EnterUpgradeableReadLock() EnterUpgradeableReadLock() EnterUpgradeableReadLock()

업그레이드 가능 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in upgradeable mode.

EnterWriteLock() EnterWriteLock() EnterWriteLock() EnterWriteLock()

쓰기 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in write mode.

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

지정한 개체와 현재 개체가 같은지 여부를 확인합니다.Determines whether the specified object is equal to the current object.

(Inherited from Object)
ExitReadLock() ExitReadLock() ExitReadLock() ExitReadLock()

읽기 모드의 재귀 횟수를 줄이고, 결과 횟수가 0이 되면 읽기 모드를 종료합니다.Reduces the recursion count for read mode, and exits read mode if the resulting count is 0 (zero).

ExitUpgradeableReadLock() ExitUpgradeableReadLock() ExitUpgradeableReadLock() ExitUpgradeableReadLock()

업그레이드 가능 모드의 재귀 횟수를 줄이고, 결과 횟수가 0이 되면 업그레이드 가능 모드를 종료합니다.Reduces the recursion count for upgradeable mode, and exits upgradeable mode if the resulting count is 0 (zero).

ExitWriteLock() ExitWriteLock() ExitWriteLock() ExitWriteLock()

쓰기 모드의 재귀 횟수를 줄이고, 결과 횟수가 0이 되면 쓰기 모드를 종료합니다.Reduces the recursion count for write mode, and exits write mode if the resulting count is 0 (zero).

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

기본 해시 함수로 작동합니다.Serves as the default hash function.

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

현재 인스턴스의 Type을 가져옵니다.Gets 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)
ToString() ToString() ToString() ToString()

현재 개체를 나타내는 문자열을 반환합니다.Returns a string that represents the current object.

(Inherited from Object)
TryEnterReadLock(Int32) TryEnterReadLock(Int32) TryEnterReadLock(Int32) TryEnterReadLock(Int32)

제한 시간(정수)을 선택적으로 적용하여 읽기 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in read mode, with an optional integer time-out.

TryEnterReadLock(TimeSpan) TryEnterReadLock(TimeSpan) TryEnterReadLock(TimeSpan) TryEnterReadLock(TimeSpan)

제한 시간을 선택적으로 적용하여 읽기 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in read mode, with an optional time-out.

TryEnterUpgradeableReadLock(Int32) TryEnterUpgradeableReadLock(Int32) TryEnterUpgradeableReadLock(Int32) TryEnterUpgradeableReadLock(Int32)

제한 시간을 선택적으로 적용하여 업그레이드 가능 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in upgradeable mode, with an optional time-out.

TryEnterUpgradeableReadLock(TimeSpan) TryEnterUpgradeableReadLock(TimeSpan) TryEnterUpgradeableReadLock(TimeSpan) TryEnterUpgradeableReadLock(TimeSpan)

제한 시간을 선택적으로 적용하여 업그레이드 가능 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in upgradeable mode, with an optional time-out.

TryEnterWriteLock(Int32) TryEnterWriteLock(Int32) TryEnterWriteLock(Int32) TryEnterWriteLock(Int32)

제한 시간을 선택적으로 적용하여 쓰기 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in write mode, with an optional time-out.

TryEnterWriteLock(TimeSpan) TryEnterWriteLock(TimeSpan) TryEnterWriteLock(TimeSpan) TryEnterWriteLock(TimeSpan)

제한 시간을 선택적으로 적용하여 쓰기 모드로 잠금을 시작하려고 합니다.Tries to enter the lock in write mode, with an optional time-out.

적용 대상

스레드 보안

이 형식은 스레드로부터 안전합니다.This type is thread safe.