İngilizce dilinde oku

Aracılığıyla paylaş


ReaderWriterLock Sınıf

Tanım

Tek yazıcıları ve birden çok okuyucuları destekleyen bir kilit tanımlar.

C#
public sealed class ReaderWriterLock : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
C#
public sealed class ReaderWriterLock
C#
[System.Runtime.InteropServices.ComVisible(true)]
public sealed class ReaderWriterLock : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
Devralma
ReaderWriterLock
Devralma
ReaderWriterLock
Öznitelikler

Örnekler

Aşağıdaki örnek, paylaşılan bir kaynağı korumak için eşzamanlı olarak okunan ve birden çok iş parçacığı tarafından özel olarak yazılan adlı resourcetamsayı değerinin nasıl kullanılacağını ReaderWriterLock gösterir. ReaderWriterLock tüm iş parçacıklarına görünür olması için sınıf düzeyinde bildirildiğini unutmayın.

C#
// The complete code is located in the ReaderWriterLock class topic.
using System;
using System.Threading;

public class Example
{
   static ReaderWriterLock rwl = new ReaderWriterLock();
   // Define the shared resource protected by the ReaderWriterLock.
   static int resource = 0;

   const int numThreads = 26;
   static bool running = true;

   // Statistics.
   static int readerTimeouts = 0;
   static int writerTimeouts = 0;
   static int reads = 0;
   static int writes = 0;

   public static void Main()
   {
      // Start a series of threads to randomly read from and
      // write to the shared resource.
      Thread[] t = new Thread[numThreads];
      for (int i = 0; i < numThreads; i++){
         t[i] = new Thread(new ThreadStart(ThreadProc));
         t[i].Name = new String((char)(i + 65), 1);
         t[i].Start();
         if (i > 10)
            Thread.Sleep(300);
      }

      // Tell the threads to shut down and wait until they all finish.
      running = false;
      for (int i = 0; i < numThreads; i++)
         t[i].Join();

      // Display statistics.
      Console.WriteLine("\n{0} reads, {1} writes, {2} reader time-outs, {3} writer time-outs.",
            reads, writes, readerTimeouts, writerTimeouts);
      Console.Write("Press ENTER to exit... ");
      Console.ReadLine();
   }

   static void ThreadProc()
   {
      Random rnd = new Random();

      // Randomly select a way for the thread to read and write from the shared
      // resource.
      while (running) {
         double action = rnd.NextDouble();
         if (action < .8)
            ReadFromResource(10);
         else if (action < .81)
            ReleaseRestore(rnd, 50);
         else if (action < .90)
            UpgradeDowngrade(rnd, 100);
         else
            WriteToResource(rnd, 100);
      }
   }

   // Request and release a reader lock, and handle time-outs.
   static void ReadFromResource(int timeOut)
   {
      try {
         rwl.AcquireReaderLock(timeOut);
         try {
            // It is safe for this thread to read from the shared resource.
            Display("reads resource value " + resource);
            Interlocked.Increment(ref reads);
         }
         finally {
            // Ensure that the lock is released.
            rwl.ReleaseReaderLock();
         }
      }
      catch (ApplicationException) {
         // The reader lock request timed out.
         Interlocked.Increment(ref readerTimeouts);
      }
   }

   // Request and release the writer lock, and handle time-outs.
   static void WriteToResource(Random rnd, int timeOut)
   {
      try {
         rwl.AcquireWriterLock(timeOut);
         try {
            // It's safe for this thread to access from the shared resource.
            resource = rnd.Next(500);
            Display("writes resource value " + resource);
            Interlocked.Increment(ref writes);
         }
         finally {
            // Ensure that the lock is released.
            rwl.ReleaseWriterLock();
         }
      }
      catch (ApplicationException) {
         // The writer lock request timed out.
         Interlocked.Increment(ref writerTimeouts);
      }
   }

   // Requests a reader lock, upgrades the reader lock to the writer
   // lock, and downgrades it to a reader lock again.
   static void UpgradeDowngrade(Random rnd, int timeOut)
   {
      try {
         rwl.AcquireReaderLock(timeOut);
         try {
            // It's safe for this thread to read from the shared resource.
            Display("reads resource value " + resource);
            Interlocked.Increment(ref reads);

            // To write to the resource, either release the reader lock and
            // request the writer lock, or upgrade the reader lock. Upgrading
            // the reader lock puts the thread in the write queue, behind any
            // other threads that might be waiting for the writer lock.
            try {
               LockCookie lc = rwl.UpgradeToWriterLock(timeOut);
               try {
                  // It's safe for this thread to read or write from the shared resource.
                  resource = rnd.Next(500);
                  Display("writes resource value " + resource);
                  Interlocked.Increment(ref writes);
               }
               finally {
                  // Ensure that the lock is released.
                  rwl.DowngradeFromWriterLock(ref lc);
               }
            }
            catch (ApplicationException) {
               // The upgrade request timed out.
               Interlocked.Increment(ref writerTimeouts);
            }

            // If the lock was downgraded, it's still safe to read from the resource.
            Display("reads resource value " + resource);
            Interlocked.Increment(ref reads);
         }
         finally {
            // Ensure that the lock is released.
            rwl.ReleaseReaderLock();
         }
      }
      catch (ApplicationException) {
         // The reader lock request timed out.
         Interlocked.Increment(ref readerTimeouts);
      }
   }

   // Release all locks and later restores the lock state.
   // Uses sequence numbers to determine whether another thread has
   // obtained a writer lock since this thread last accessed the resource.
   static void ReleaseRestore(Random rnd, int timeOut)
   {
      int lastWriter;

      try {
         rwl.AcquireReaderLock(timeOut);
         try {
            // It's safe for this thread to read from the shared resource,
            // so read and cache the resource value.
            int resourceValue = resource;     // Cache the resource value.
            Display("reads resource value " + resourceValue);
            Interlocked.Increment(ref reads);

            // Save the current writer sequence number.
            lastWriter = rwl.WriterSeqNum;

            // Release the lock and save a cookie so the lock can be restored later.
            LockCookie lc = rwl.ReleaseLock();

            // Wait for a random interval and then restore the previous state of the lock.
            Thread.Sleep(rnd.Next(250));
            rwl.RestoreLock(ref lc);

            // Check whether other threads obtained the writer lock in the interval.
            // If not, then the cached value of the resource is still valid.
            if (rwl.AnyWritersSince(lastWriter)) {
               resourceValue = resource;
               Interlocked.Increment(ref reads);
               Display("resource has changed " + resourceValue);
            }
            else {
               Display("resource has not changed " + resourceValue);
            }
         }
         finally {
            // Ensure that the lock is released.
            rwl.ReleaseReaderLock();
         }
      }
      catch (ApplicationException) {
         // The reader lock request timed out.
         Interlocked.Increment(ref readerTimeouts);
      }
   }

   // Helper method briefly displays the most recent thread action.
   static void Display(string msg)
   {
      Console.Write("Thread {0} {1}.       \r", Thread.CurrentThread.Name, msg);
   }
}

Açıklamalar

Önemli

.NET Framework iki okuyucu yazıcı kilidi vardır ReaderWriterLockSlim ve ReaderWriterLock. ReaderWriterLockSlim tüm yeni geliştirmeler için önerilir. ReaderWriterLockSlim ile benzerdir ReaderWriterLock, ancak özyineleme ve kilit durumunu yükseltme ve düşürme için basitleştirilmiş kuralları vardır. ReaderWriterLockSlim olası kilitlenme durumlarını önler. Buna ek olarak, performansı değerinden ReaderWriterLockSlim önemli ölçüde daha ReaderWriterLockiyidir.

ReaderWriterLock bir kaynağa erişimi eşitlemek için kullanılır. Herhangi bir zamanda, birden çok iş parçacığı için eşzamanlı okuma erişimine veya tek bir iş parçacığı için yazma erişimine izin verir. Bir kaynağın seyrek olarak değiştirildiği bir durumda, ReaderWriterLock gibi tek seferde basit bir kilitten Monitordaha iyi aktarım hızı sağlar.

ReaderWriterLock çoğu erişimin okunduğu, yazma işlemlerinin ise seyrek ve kısa süreli olduğu durumlarda en iyi sonucu verir. Birden çok okuyucu tek yazıcılarla birlikte alternatif olarak, okuyucuların veya yazarların uzun süreler boyunca engellenmemesi için.

Not

Okuyucu kilitlerini veya yazıcı kilitlerini uzun süre tutmak diğer iş parçacıklarını aç bırakacaktır. En iyi performans için, yazma işlemlerinin süresini en aza indirmek için uygulamanızı yeniden yapılandırmayı göz önünde bulundurun.

bir iş parçacığı bir okuyucu kilidini veya yazıcı kilidini tutabilir, ancak aynı anda ikisini birden tutamaz. Yazıcı kilidini almak için bir okuyucu kilidi bırakmak yerine ve DowngradeFromWriterLockkullanabilirsinizUpgradeToWriterLock.

Özyinelemeli kilit istekleri, kilit üzerindeki kilit sayısını artırır.

Okuyucular ve yazarlar ayrı ayrı kuyruğa alınıyor. Bir iş parçacığı yazıcı kilidini serbest bıraktığında, o anda okuyucu kuyruğunda bekleyen tüm iş parçacıklarına okuyucu kilitleri verilir; Tüm bu okuyucu kilitleri serbest bırakıldığında, varsa yazıcı kuyruğunda bekleyen bir sonraki iş parçacığına yazıcı kilidi verilir ve bu şekilde devam eder. Başka bir deyişle, ReaderWriterLock bir okuyucu koleksiyonu ile bir yazar arasında geçiş sağlar.

Yazıcı kuyruğundaki bir iş parçacığı etkin okuyucu kilitlerinin yayımlanmasını beklerken, yeni okuyucu kilitleri isteyen iş parçacıkları okuyucu kuyruğunda birikir. Mevcut okuyucu kilidi sahipleriyle eşzamanlı erişim paylaşabilseler bile istekleri verilmez; bu, yazarların okuyucular tarafından süresiz engellenmesine karşı korunmasına yardımcı olur.

Kabul edilen zaman aşımı değerlerinde ReaderWriterLock kilit alma yöntemlerinin çoğu. Uygulamanızda kilitlenmeleri önlemek için zaman aşımlarını kullanın. Örneğin, bir iş parçacığı bir kaynakta yazıcı kilidini alabilir ve ardından ikinci bir kaynakta okuyucu kilidi isteyebilir; bu arada, başka bir iş parçacığı ikinci kaynakta yazıcı kilidini alabilir ve ilkinde bir okuyucu kilidi isteyebilir. Zaman aşımları kullanılmadığı sürece iş parçacıkları kilitlenmez.

Zaman aşımı aralığının süresi dolarsa ve kilit isteği verilmediyse, yöntemi bir ApplicationExceptionoluşturarak denetimi çağıran iş parçacığına döndürür. bir iş parçacığı bu özel durumu yakalayabilir ve bundan sonra hangi eylemin gerçekleştirileceğini belirleyebilir.

Zaman aşımları milisaniye cinsinden ifade edilir. Zaman aşımını belirtmek için bir System.TimeSpan kullanırsanız, kullanılan değer ile TimeSpantemsil edilen toplam milisaniye sayısıdır. Aşağıdaki tabloda geçerli zaman aşımı değerleri milisaniye cinsinden gösterilmektedir.

Değer Açıklama
-1 İş parçacığı, ne kadar sürdüğüne bakılmaksızın kilit alınana kadar bekler. Tamsayı zaman aşımlarını belirten yöntemler için sabit Infinite kullanılabilir.
0 İş parçacığı kilidi almak için beklemez. Kilit hemen alınamazsa, yöntem döndürür.
>0 Beklenen milisaniye sayısı.

-1 dışında, negatif zaman aşımı değerlerine izin verilmez. -1 dışında bir negatif tamsayı belirtirseniz, bunun yerine sıfır zaman aşımı değeri kullanılır. (Yani, kilit hemen alınamazsa yöntem beklemeden döner.) -1 dışında negatif bir milisaniye sayısını temsil eden bir TimeSpan belirtirseniz, ArgumentOutOfRangeException oluşturulur.

Oluşturucular

ReaderWriterLock()

ReaderWriterLock sınıfının yeni bir örneğini başlatır.

Özellikler

IsReaderLockHeld

Geçerli iş parçacığının okuyucu kilidi barındırıp tutmadığını belirten bir değer alır.

IsWriterLockHeld

Geçerli iş parçacığının yazıcı kilidini barındırıp tutmadığını belirten bir değer alır.

WriterSeqNum

Geçerli sıra numarasını alır.

Yöntemler

AcquireReaderLock(Int32)

Zaman aşımı için bir değer kullanarak bir Int32 okuyucu kilidi alır.

AcquireReaderLock(TimeSpan)

Zaman aşımı için bir değer kullanarak bir TimeSpan okuyucu kilidi alır.

AcquireWriterLock(Int32)

Zaman aşımı için bir Int32 değer kullanarak yazıcı kilidini alır.

AcquireWriterLock(TimeSpan)

Zaman aşımı için bir TimeSpan değer kullanarak yazıcı kilidini alır.

AnyWritersSince(Int32)

Sıra numarası elde edildikten sonra yazıcı kilidinin herhangi bir iş parçacığına verilip verilmediğini gösterir.

DowngradeFromWriterLock(LockCookie)

İş parçacığının kilit durumunu daha önce UpgradeToWriterLock(Int32) çağrıldığı duruma geri yükler.

Equals(Object)

Belirtilen nesnenin geçerli nesneye eşit olup olmadığını belirler.

(Devralındığı yer: Object)
Finalize()

Atık toplayıcı nesneyi geri kazandığında kaynakların serbest kalmasını ve diğer temizleme işlemlerinin gerçekleştirilmesini ReaderWriterLock sağlar.

GetHashCode()

Varsayılan karma işlevi işlevi görür.

(Devralındığı yer: Object)
GetType()

Type Geçerli örneğini alır.

(Devralındığı yer: Object)
MemberwiseClone()

Geçerli Objectöğesinin sığ bir kopyasını oluşturur.

(Devralındığı yer: Object)
ReleaseLock()

İş parçacığının kilidi kaç kez aldığına bakılmaksızın kilidi serbest bırakır.

ReleaseReaderLock()

Kilit sayısını azaltma.

ReleaseWriterLock()

Yazıcı kilidindeki kilit sayısını azaltma.

RestoreLock(LockCookie)

İş parçacığının kilit durumunu çağırmadan ReleaseLock()önceki durumuna geri yükler.

ToString()

Geçerli nesneyi temsil eden dizeyi döndürür.

(Devralındığı yer: Object)
UpgradeToWriterLock(Int32)

Zaman aşımı için bir Int32 değer kullanarak okuyucu kilidini yazıcı kilidine yükselter.

UpgradeToWriterLock(TimeSpan)

Zaman aşımı için bir TimeSpan değer kullanarak okuyucu kilidini yazıcı kilidine yükselter.

Şunlara uygulanır

Ürün Sürümler
.NET Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9, 10
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

İş Parçacığı Güvenliği

Bu güvenli iş parçacığı türüdür.

Ayrıca bkz.