C#多线程中锁的使用

最近的项目中涉及到实时数据的处理,经常会使用多线程访问共享资源。如果处理不当,资源未能正确在各个线程中同步的话,计算结果将会出现错误。


关于资源同步最常用的技术就是加锁。这里提到是一个比较简单的锁 -- lock。 lock是对monitor中的两个函数enter和exit的封装。


当时项目的模式是这样的:有一个类中有个共享的资源(List),这个类会开辟两个线程分别对它进行读和写操作,而且这个类会有多个实例,每个实例都会在一个线程中。


其工作模式如下图所示:




这里的写线程将会动态改变list里面的值已经值对应的index,而读的线程会先用一个匹配的函数找出需要的值对应的index,然后根据index取出其中的值加以计算。


在这种模式中,如果读线程去访问list数据时,写线程对list进行了修改,就会导致结果出错。因此我们需要引入锁的机制。那么问题来了,我们是要在读的线程中加锁,还是在写的线程中加锁。而且加锁的话,是采用什么方式?


以下有几种方式,将会一一分析其对错。


1. 使用对象本身作为锁对象,对写线程进行加锁


使用这种方式,在写线程中,list将会被锁定,执行完毕之后释放锁。然而这种模式还是会得出错误结果,假设在读线程中先对list进行了匹配并取出了需要的index,这时写线程获取了锁,并对list进行了修改,之后释放list,读线程根据index查找list对应的值,然而此时list已被更改。


2. 使用对象本身作为锁对象,对读线程进行加锁


使用这种方式,在读线程中,list将会被锁定,所以读的过程中list都将保持不变。


除了使用对象本身作为锁对象之外,还可以使用其他的引用类型,比如System.Object,此时线程不会访问该类型的任何属性和方法,改对象的作用仅仅是协调各个线程。


3. 使用System.Object作为锁对象


根据上面的分析,我们将只对读线程进行加锁。但是这时又有两种情况:object对象可以定义成实例对象和静态对象。目前的这种模式适用于把锁加在实例对象的object上。因为使用object作为锁对象时,操作流程时占有A,操作B,释放A。若将object定义为静态对象,此时对object进行加锁,将协调的是类的每个实例所产生的对象,对应的list也必须是静态的。而这里我们需要协调的是某一个实例中的两个线程,因此需要将object定义为实例对象。


综上所述,有两种方式可以实现以上模式的线程同步,一种是使用对象本身作为锁对象,对读线程进行加锁,另一种是使用实例对象的System.Object作为锁对象,对读线程进程加锁。



  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值