C# ReaderWriterLock类学习

前言

今天这篇文章我们来学习一下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

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C# 中,线程并发和线程同步是处理多线程编程中重要的概念。 线程并发指的是多个线程同时执行,这可能导致资源竞争和不确定的结果。为了避免这种情况,我们可以使用线程同步机制来确保线程之间的协调和有序执行。 C# 提供了多种线程同步的机制,下面是一些常用的方法: 1. 互斥锁(Mutex):互斥锁是一种排他锁,只允许一个线程访问被保护的资源。可以使用 `Mutex` 来创建和管理互斥锁。 2. 信号量(Semaphore):信号量是一种计数器,用于控制同时访问某个资源的线程数。可以使用 `Semaphore` 来创建和管理信号量。 3. 自旋锁(SpinLock):自旋锁是一种忙等待锁,线程会一直尝试获取锁,直到成功为止。可以使用 `SpinLock` 结构来创建和管理自旋锁。 4. 互斥量(Mutex):互斥量是一种特殊的信号量,只能被一个线程持有。可以使用 `Mutex` 来创建和管理互斥量。 5. 事件(Event):事件是一种同步机制,在多个线程之间发送信号进行通信。可以使用 `ManualResetEvent` 或 `AutoResetEvent` 来创建和管理事件。 除了上述方法外,还有一些其他的线程同步机制,如读写锁(ReaderWriterLock)、条件变量(Monitor)等。选择适合场景的线程同步机制很重要,以确保线程安全和性能。 需要注意的是,线程并发和线程同步是一个复杂的主题,需要深入学习和实践才能掌握。在编写多线程代码时,建议仔细考虑并发问题,并使用适当的线程同步机制来确保代码的正确性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IC00

打赏就发新文

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值