C# ReaderWriterLock类学习

发布时间:2024年01月08日

前言

今天这篇文章我们来学习一下ReaderWriterLock类,ReaderWriterLock类定义了实现单写程序和多读程序语义的锁。这个类主要用于文件操作,即多个线程可以读取文件,但只能用一个线程来更新文件。使用ReaderWriterLock类时,任意数量的线程都可以同时安全地读取数据。只有当线程进行更新时,数据才被锁定。只有在没有占用锁的写程序线程时,读程序线程才能获得锁。只有在没有占用锁的读程序或者写程序线程时,写程序线程才能获得锁。

12354689123110.gif

ReaderWriterLock类概念

ReaderWriterLock 用于同步对资源的访问。在任何给定时间,它都允许对多个线程进行并发读取访问,或允许对单个线程进行写入访问。 在资源不频繁更改的情况下,提供 ReaderWriterLock 比简单的一次性锁(例如 Monitor)更好的吞吐量。ReaderWriterLock 在大多数访问是读取的最好位置,而写入频率不常且持续时间较短。 多个读取器与单个编写器交替,这样读者和编写器都不会长期被阻止

C# (2).png

ReaderWriterLock类方法和属性

构造函数
ReaderWriterLock()
初始化 ReaderWriterLock 类的新实例。

属性
IsReaderLockHeld
获取一个值,该值指示当前线程是否持有读线程锁。
IsWriterLockHeld
获取一个值,该值指示当前线程是否持有写线程锁。
WriterSeqNum
获取当前序列号。

方法
AcquireReaderLock(Int32)
使用一个 Int32 超时值获取读线程锁。
AcquireReaderLock(TimeSpan)
使用一个 TimeSpan 超时值获取读线程锁。
AcquireWriterLock(Int32)
使用一个 Int32 超时值获取写线程锁。
AcquireWriterLock(TimeSpan)
使用一个 TimeSpan 超时值获取写线程锁
AnyWritersSince(Int32)
指示获取序列号之后是否已将写线程锁授予某个线程。
DowngradeFromWriterLock(LockCookie)
将线程的锁状态还原为调用 UpgradeToWriterLock(Int32) 前的状态。
Equals(Object)
确定指定对象是否等于当前对象。(继承自 Object)
Finalize()
确保垃圾回收器回收 ReaderWriterLock 对象时释放资源并执行其他清理操作。
GetHashCode()
作为默认哈希函数。(继承自 Object)
GetType()
获取当前实例的 Type。(继承自 Object)
MemberwiseClone()
创建当前 Object 的浅表副本。(继承自 Object)
ReleaseLock()
释放锁,不管线程获取锁的次数如何。
ReleaseReaderLock()
减少锁计数。
ReleaseWriterLock()
减少写线程锁上的锁计数。
RestoreLock(LockCookie)
将线程的锁状态还原为调用 ReleaseLock() 前的状态。
ToString()
返回表示当前对象的字符串。(继承自 Object)
UpgradeToWriterLock(Int32)
使用一个 Int32 超时值将读线程锁升级为写线程锁。
UpgradeToWriterLock(TimeSpan)
使用一个 TimeSpan 超时值将读线程锁升级为写线程锁。

代码示例

线程wt1和wt2是在WriteInts()方法中获取写程序锁的写程序线程,线程rt1和rt2是在ReadInts()方法中获取读程序锁的读程序线程。在WriteInts()方法中,实例变量x和y分别变为新值a和b。当线程wt1或wt2通过调用AcqireWriteLock()获取写程序锁时,其他线程(包括读程序线程rt1和rt2)就不能访问对象,直到线程wt1和wt2通过调用ReleaseWriterLock()释放了写程序锁。在ReadInts()方法中,线程rt1和rt2通ReleaseWriterLock()释放了写程序锁。在ReadInts()方法中,线程rt1和rt2通过调用 AcquireReadLock()方法获得读程序锁。在ReadInts()方法中,线程rt1和rt2可以同时访问实例变量x和y。写程序线程(wt1和wt2)都无法访问对象,直到读程序释放读程序锁。在获取读程序锁后,读程序线程才能同时访问对象

 using  System;
 using  System.Threading;
 using  System.Runtime.CompilerServices;
 public   class  ClassForMain
 {
    public class ReadWrite
    {
       private ReaderWriterLock rwl;
        private int x;
        private int y;
        public ReadWrite()
        {
            rwl = new ReaderWriterLock();
        }
        public void ReadInts(ref int a, ref int b)
        {
            rwl.AcquireReaderLock(Timeout.Infinite);
            try
            {
                a = this.x;
                b = this.y;
            }
            finally
            {
               rwl.ReleaseReaderLock();
            }
        }
        public void WriteInts(int a, int b)
        {
            rwl.AcquireWriterLock(Timeout.Infinite);
            this.x = a;
            this.y = b;
            try
            {
                Console.WriteLine("Begin write...");
                Console.WriteLine("x=" + this.x + "y=" + this.y + "ThreadID=" +
                Thread.CurrentThread.GetHashCode());
            }
            finally
            {
                rwl.ReleaseWriterLock();
                Console.WriteLine("End write!");
            }
        }
        public class RWApp
        {
            private ReadWrite rw = new ReadWrite();
            public static void Main(string[] args)
            {
                RWApp e = new RWApp();
                //Write Threads
                Thread wl1 = new Thread(new ThreadStart(e.Write));
                wl1.Start();
                Thread wl2 = new Thread(new ThreadStart(e.Write));
                wl2.Start();       
                //Reader Threads
                Thread rt1 = new Thread(new ThreadStart(e.Read));
                rt1.Start();
                Thread rt2 = new Thread(new ThreadStart(e.Read));
                rt2.Start();
                Thread rt3 = new Thread(new ThreadStart(e.Read));
                rt3.Start();
            }
            private void Write()
            {
                int a = 10;
                int b = 11;
                for (int i = 0; i < 5; i++)
                {
                    this.rw.WriteInts(a++, b++);
                    Thread.Sleep(1000);
                }
            }
            private void Read()
            {
                int a = 10;
                int b = 11;
                for (int i = 0; i < 5; i++)
                {
                    this.rw.ReadInts(ref a, ref b);
                    Console.WriteLine("For i=" + i + "||a=" + a + "||b=" + b +
                    "ThreadID=" + Thread.CurrentThread.GetHashCode());
                    Thread.Sleep(1000);
                }
            }
        }
    }
}

总结:

这篇文章比较简单,只是简单的学习一下,等博主有时间了出一篇详细的保姆级文章,对它有更多的认识,在有需求的时候最起码有路子,虽然很简单,但是也是可以学到东西的,我们学习了新的知识,对我们的知识储备及技术又有新的一点点的进步,C#的技术就是先简单再难嘛,积少成多之后才会成长才会进步,我们要不断的学习不断的探索,才能有学习的动力,才会有学习的欲望,创作不易,点赞评论收藏关注,嘿嘿,不喜勿喷!!!!

1235468900

文章来源:https://blog.csdn.net/qq_46104786/article/details/135452938
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。