简易的读写锁 SmartRWLocker--ESBasic 可复用的.NET类库(10)
2009-10-10 16:16
393 查看
1.缘起:
对于需要进行线程同步的地方,我们经常用的就是.NET内置的lock关键字和ReaderWriterLock类。lock的功能相对简单,因为它不区分读写,也就是说如果都在lock块中,读线程都会阻塞另一个读线程,在很多读远远多于写的应用中,这会极大地折损性能。所以我们也经常需要使用读写分离的锁ReaderWriterLock,使用它,我们可以明确的指定是要获取“读”锁还是“写”锁。而且,当前的“读”线程是不会阻塞其它的“读”线程的。
lock的使用非常简洁,而ReaderWriterLock类的使用就要繁琐很多,比如像这样:
private ReaderWriterLock readerWriterLock = new ReaderWriterLock();
public void Test()
{
try
{
this.readerWriterLock.AcquireWriterLock(-1);
// Do Something
}
finally
{
this.readerWriterLock.ReleaseWriterLock();
}
}
于是,我设计了ESBasic.Threading.Synchronize.SmartRWLocker来简化ReaderWriterLock的使用,使得我们可以像使用lock一样来使用ReaderWriterLock。
2.适用场合:
在大多数使用ReaderWriterLock的地方都可以使用SmartRWLocker来代替,除非你需要使用某些ReaderWriterLock的特殊功能。SmartRWLocker适用于以下场合:
(1)需要使用读写分离的锁。
(2)不需要设置等待锁的超时时间,也就是无限期地等待锁。
(3)不需要升级/降级锁,如将读锁升级为写锁,或将写锁降级为读锁。
3.设计思想与实现
SmartRWLocker的类图如下:
我们看到SmartRWLocker内部就是借助ReaderWriterLock来实现锁的控制的。而SmartRWLocker只有一个Lock方法,参数是一个AccessMode枚举,表示调用者是希望获取读锁还是写锁,另外该方法返回一个LockingObject对象。LockingObject的生命周期很有意思,LockingObject对象产生的时候,就是获取锁的时刻,其被销毁的时候(Dispose方法),就是释放锁的时刻。所以LockingObject对象的生命周期就是占用锁的时间段。
IDisposable接口与using结合起来使用,会使得语法非常简单可读。我们可以这样来简洁地使用SmartRWLocker:
private SmartRWLocker smartRWLocker = new SmartRWLocker();
public void Test2()
{
using(this.smartRWLocker.Lock(AccessMode.Write))
{
// Do Something
}
}
这就非常类似lock的使用方式了。
最后,LastRequireReadTime和LastRequireWriteTime属性记录了最后一次获取读写锁的时间 -- 即从一个侧面记录了我们对目标资源最后一次进行读写的时间。
4. 使用时的注意事项
SmartRWLocker简化了ReaderWriterLock的使用,但是正如有得必有失,它也损失了一些ReaderWriterLock的功能,正如在适用场合中介绍的,使用SmartRWLocker无法设置获取锁的超时时间,也无法升级/降级锁的性质。幸运的是,大多数情况下,我们都用不到这些高级一点的特性,所以,SmartRWLocker还是有它存在的价值的。
如果你的应用需要使用SmartRWLocker不提供的特性,那只有转向使用ReaderWriterLock本身了。这也未必是个坏主意。
使用任何类型的锁的时候,你都需要注意锁的“粒度”的问题,即你的锁要锁住的范围有多大。粒度太大,会降低系统的并发;粒度太细,又会使得编程相当繁琐。所以在设计时需要进行权衡,为你的锁选择一个恰当的粒度是非常重要的。
5.扩展
简易的读写锁SmartRWLocker暂时没有任何扩展。
注: ESBasic已经开源,点击这里下载源码。
ESBasic开源前言
对于需要进行线程同步的地方,我们经常用的就是.NET内置的lock关键字和ReaderWriterLock类。lock的功能相对简单,因为它不区分读写,也就是说如果都在lock块中,读线程都会阻塞另一个读线程,在很多读远远多于写的应用中,这会极大地折损性能。所以我们也经常需要使用读写分离的锁ReaderWriterLock,使用它,我们可以明确的指定是要获取“读”锁还是“写”锁。而且,当前的“读”线程是不会阻塞其它的“读”线程的。
lock的使用非常简洁,而ReaderWriterLock类的使用就要繁琐很多,比如像这样:
private ReaderWriterLock readerWriterLock = new ReaderWriterLock();
public void Test()
{
try
{
this.readerWriterLock.AcquireWriterLock(-1);
// Do Something
}
finally
{
this.readerWriterLock.ReleaseWriterLock();
}
}
于是,我设计了ESBasic.Threading.Synchronize.SmartRWLocker来简化ReaderWriterLock的使用,使得我们可以像使用lock一样来使用ReaderWriterLock。
2.适用场合:
在大多数使用ReaderWriterLock的地方都可以使用SmartRWLocker来代替,除非你需要使用某些ReaderWriterLock的特殊功能。SmartRWLocker适用于以下场合:
(1)需要使用读写分离的锁。
(2)不需要设置等待锁的超时时间,也就是无限期地等待锁。
(3)不需要升级/降级锁,如将读锁升级为写锁,或将写锁降级为读锁。
3.设计思想与实现
SmartRWLocker的类图如下:
我们看到SmartRWLocker内部就是借助ReaderWriterLock来实现锁的控制的。而SmartRWLocker只有一个Lock方法,参数是一个AccessMode枚举,表示调用者是希望获取读锁还是写锁,另外该方法返回一个LockingObject对象。LockingObject的生命周期很有意思,LockingObject对象产生的时候,就是获取锁的时刻,其被销毁的时候(Dispose方法),就是释放锁的时刻。所以LockingObject对象的生命周期就是占用锁的时间段。
IDisposable接口与using结合起来使用,会使得语法非常简单可读。我们可以这样来简洁地使用SmartRWLocker:
private SmartRWLocker smartRWLocker = new SmartRWLocker();
public void Test2()
{
using(this.smartRWLocker.Lock(AccessMode.Write))
{
// Do Something
}
}
这就非常类似lock的使用方式了。
最后,LastRequireReadTime和LastRequireWriteTime属性记录了最后一次获取读写锁的时间 -- 即从一个侧面记录了我们对目标资源最后一次进行读写的时间。
4. 使用时的注意事项
SmartRWLocker简化了ReaderWriterLock的使用,但是正如有得必有失,它也损失了一些ReaderWriterLock的功能,正如在适用场合中介绍的,使用SmartRWLocker无法设置获取锁的超时时间,也无法升级/降级锁的性质。幸运的是,大多数情况下,我们都用不到这些高级一点的特性,所以,SmartRWLocker还是有它存在的价值的。
如果你的应用需要使用SmartRWLocker不提供的特性,那只有转向使用ReaderWriterLock本身了。这也未必是个坏主意。
使用任何类型的锁的时候,你都需要注意锁的“粒度”的问题,即你的锁要锁住的范围有多大。粒度太大,会降低系统的并发;粒度太细,又会使得编程相当繁琐。所以在设计时需要进行权衡,为你的锁选择一个恰当的粒度是非常重要的。
5.扩展
简易的读写锁SmartRWLocker暂时没有任何扩展。
注: ESBasic已经开源,点击这里下载源码。
ESBasic开源前言
相关文章推荐
- ESBasic 可复用的.NET类库(10) -- 简易的读写锁 SmartRWLocker
- ESBasic 可复用的.NET类库(14) -- 优先级管理器 IPriorityManager
- ESBasic 可复用的.NET类库(12) -- 对象管理器 IObjectManager
- ESBasic 可复用的.NET类库(16) -- 定时刷新缓存管理器 IRefreshableCacheManager
- ESBasic 可复用的.NET类库(00) -- 开源前言
- ESBasic 可复用的.NET类库(09) -- 心跳监测器 IHeartBeatChecker
- ESBasic 可复用的.NET类库(00) -- 开源前言(附下载)
- ESBasic 可复用的.NET类库(01) -- 时刻 ShortTime
- 回调定时器ICallbackTimer --ESBasic 可复用的.NET类库(07)
- 热缓存 IHotCache --ESBasic 可复用的.NET类库(19)
- 时刻 ShortTime --ESBasic 可复用的.NET类库(01)
- 遵循Spring大纲的XML(反)序列化 SpringFox --ESBasic 可复用的.NET类库(27)
- 循环引擎 ICycleEngine --ESBasic 可复用的.NET类库(04)
- ESBasic 可复用的.NET类库(24) -- 层级结构缓存IHiberarchyCache
- ESBasic 可复用的.NET类库(25) -- 增量自动获取器 IIncreaseAutoRetriever
- ESBasic 可复用的.NET类库(15) -- 对象池 IObjectPool
- ESBasic 可复用的.NET类库(04) -- 循环引擎 ICycleEngine
- ESBasic 可复用的.NET类库(13) -- 分组对象管理器 IGroupingObjectManager
- 日期 Date--ESBasic 可复用的.NET类库(02)
- 圈 Circle--ESBasic 可复用的.NET类库(03)