锁的封装 读写锁、lock
最近由于项目上面建议使用读写锁,而去除常见的lock锁。然后就按照需求封装了下锁。以简化锁的使用。但是开发C#的童鞋都知道lock关键字用起太方便了,但是lock关键字不支持超时处理。很无奈,为了实现类似lock的功能。于是通过使用using关键字和IDisposable实现了自己的锁方法
- class Program
- {
- static void Main(string[] args)
- {
- ReadWriteUtilTest();
- MonitorUtilTest();
- Console.ReadLine();
- }
- private static void MonitorUtilTest()
- {
- MonitorUtil util = new MonitorUtil();
- int num = ;
- for (int index = ; index < ; index++)
- {
- var th = new Thread(new ThreadStart(() =>
- {
- Thread.Sleep();
- for (int i = ; i < ; i++)
- {
- using (util.GetLock("hello"))
- {
- num++;
- Console.WriteLine("num={0}", num);
- }
- }
- }));
- th.Start();
- }
- }
- private static void ReadWriteUtilTest()
- {
- ReadWriteLockUtil utl = new ReadWriteLockUtil();
- Int32 num = ;
- for (var i = ; i < ; i++)
- {
- Task.Factory.StartNew(() =>
- {
- while (true)
- {
- using (utl.GetLock("hello", ReadWriteLockUtil.ReadWriteEnum.Read))
- {
- Console.WriteLine("num={0}", num);
- Thread.Sleep();
- }
- }
- });
- }
- Task.Factory.StartNew(() =>
- {
- while (true)
- {
- using (utl.GetLock("hello", ReadWriteLockUtil.ReadWriteEnum.Write))
- {
- num++;
- Thread.Sleep();
- }
- Thread.Sleep();
- }
- });
- }
- }
- /// <summary>
- /// 排他锁工具类
- /// </summary>
- public class MonitorUtil
- {
- /// <summary>
- /// 自定义锁对象
- /// </summary>
- internal class CustMonitor : IDisposable
- {
- /// <summary>
- /// 锁对象
- /// </summary>
- private Object lockObj = null;
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="lockObj">锁对象</param>
- public CustMonitor(Object lockObj)
- {
- this.lockObj = lockObj;
- }
- /// <summary>
- /// 锁释放
- /// </summary>
- public void Dispose()
- {
- try
- {
- Monitor.Exit(this.lockObj);
- }
- catch
- {
- // 当前线程如果没有获取到锁时,则会抛出异常。此处直接吞掉
- }
- }
- }
- /// <summary>
- /// 锁信息
- /// </summary>
- internal class LockInfo
- {
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="lockObj">锁实例</param>
- /// <param name="custMonitor">自定义锁对象</param>
- public LockInfo(Object lockObj, CustMonitor custMonitor)
- {
- this.CustMonitor = custMonitor;
- this.LockObj = lockObj;
- }
- /// <summary>
- /// 自定义锁对象
- /// </summary>
- public CustMonitor CustMonitor { get; private set; }
- /// <summary>
- /// 锁实例
- /// </summary>
- public Object LockObj { get; private set; }
- }
- /// <summary>
- /// 锁集合
- /// </summary>
- private ConcurrentDictionary<String, LockInfo> lockObjData = new ConcurrentDictionary<String, LockInfo>();
- /// <summary>
- /// lockObjData同步对象
- /// </summary>
- private Object custLockObj = new Object();
- /// <summary>
- /// 获取锁对象
- /// </summary>
- /// <param name="lockName">返回锁对象</param>
- /// <param name="waitTime">等待时间(单位:毫秒)</param>
- /// <returns>返回锁对象</returns>
- /// <exception cref="TimeoutException">获取锁对象超时时,抛出此异常</exception>
- public IDisposable GetLock(String lockName, Int32 waitTime = )
- {
- // 获取锁对象
- var lockObj = GetLockInfo(lockName);
- // 规范等待时间长
- if (waitTime <= )
- {
- // 进入锁
- Monitor.Enter(lockObj.LockObj);
- }
- else
- {
- // 进入锁
- if (Monitor.TryEnter(lockObj.LockObj, waitTime) == false)
- {
- return lockObj.CustMonitor;
- //throw new TimeoutException("等待锁超时");
- }
- }
- return lockObj.CustMonitor;
- }
- /// <summary>
- /// 获取锁对象信息
- /// </summary>
- /// <param name="lockName">锁名称</param>
- /// <returns>返回锁对象</returns>
- private LockInfo GetLockInfo(String lockName)
- {
- LockInfo lockObj = null;
- // 懒汉方式,先获取一次锁对象
- if (lockObjData.ContainsKey(lockName))
- {
- lockObj = lockObjData[lockName];
- }
- else
- {
- lock (custLockObj)
- {
- if (lockObjData.ContainsKey(lockName))
- {
- lockObj = lockObjData[lockName];
- }
- else
- {
- // 如果获取不到锁,则创建一个锁对象
- var lockInstance = new Object();
- lockObj = new LockInfo(lockInstance, new CustMonitor(lockInstance));
- lockObjData[lockName] = lockObj;
- }
- }
- }
- return lockObj;
- }
- }
- /// <summary>
- /// 读写锁工具类
- /// </summary>
- public class ReadWriteLockUtil
- {
- /// <summary>
- /// 自定义锁对象
- /// </summary>
- internal class CustMonitor : IDisposable
- {
- /// <summary>
- /// 获取方式
- /// </summary>
- private ReadWriteEnum getType;
- /// <summary>
- /// 锁对象
- /// </summary>
- private ReaderWriterLockSlim lockObj = null;
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="lockObj">锁对象</param>
- /// <param name="getType">获取方式</param>
- public CustMonitor(ReaderWriterLockSlim lockObj, ReadWriteEnum getType)
- {
- this.lockObj = lockObj;
- this.getType = getType;
- }
- /// <summary>
- /// 锁释放
- /// </summary>
- public void Dispose()
- {
- if (getType == ReadWriteEnum.Read && lockObj.IsReadLockHeld)
- {
- lockObj.ExitReadLock();
- }
- else if (getType == ReadWriteEnum.Write && lockObj.IsWriteLockHeld)
- {
- lockObj.ExitWriteLock();
- }
- }
- }
- /// <summary>
- /// 读写枚举
- /// </summary>
- public enum ReadWriteEnum
- {
- /// <summary>
- /// 读
- /// </summary>
- Read,
- /// <summary>
- /// 写
- /// </summary>
- Write
- }
- /// <summary>
- /// 锁集合
- /// </summary>
- private ConcurrentDictionary<String, ReaderWriterLockSlim> lockObjData = new ConcurrentDictionary<String, ReaderWriterLockSlim>();
- /// <summary>
- /// lockObjData同步对象
- /// </summary>
- private Object custLockObj = new Object();
- /// <summary>
- /// 获取锁对象
- /// </summary>
- /// <param name="lockName">返回锁对象</param>
- /// <param name="getType">获取方式</param>
- /// <param name="waitTime">等待时间(单位:毫秒),大于0,则等待指定时间,非正数,则死等</param>
- /// <returns>返回锁对象</returns>
- /// <exception cref="TimeoutException">获取锁对象超时时,抛出此异常</exception>
- public IDisposable GetLock(String lockName, ReadWriteEnum getType, Int32 waitTime = )
- {
- // 获取锁对象
- var lockInfo = GetLockInfo(lockName);
- // 规范等待时间长
- if (waitTime <= )
- {
- // 进入锁
- return GetLockByInfiniteWait(lockName, getType);
- }
- // 进入锁
- if (getType == ReadWriteEnum.Read)
- {
- if (lockInfo.IsReadLockHeld || lockInfo.TryEnterReadLock(waitTime))
- {
- return new CustMonitor(lockInfo, getType);
- }
- throw new TimeoutException("等待读锁超时");
- }
- else if (getType == ReadWriteEnum.Write)
- {
- if (lockInfo.IsWriteLockHeld || lockInfo.TryEnterWriteLock(waitTime))
- {
- return new CustMonitor(lockInfo, getType);
- }
- throw new TimeoutException("等待写锁超时");
- }
- return null;
- }
- /// <summary>
- /// 获取锁对象,获取过程会死等。直到获取到锁对象
- /// </summary>
- /// <param name="lockName">锁名称</param>
- /// <param name="getType">获取方式</param>
- /// <returns>返回锁对象</returns>
- private IDisposable GetLockByInfiniteWait(String lockName, ReadWriteEnum getType)
- {
- // 获取锁对象
- var lockObj = GetLockInfo(lockName);
- // 进入锁
- if (getType == ReadWriteEnum.Read)
- {
- lockObj.EnterReadLock();
- return new CustMonitor(lockObj, getType);
- }
- else if (getType == ReadWriteEnum.Write)
- {
- lockObj.EnterWriteLock();
- return new CustMonitor(lockObj, getType);
- }
- return null;
- }
- /// <summary>
- /// 获取锁对象信息
- /// </summary>
- /// <param name="lockName">锁名称</param>
- /// <returns>返回锁对象</returns>
- private ReaderWriterLockSlim GetLockInfo(String lockName)
- {
- ReaderWriterLockSlim lockObj = null;
- // 懒汉方式,先获取一次锁对象
- if (lockObjData.ContainsKey(lockName))
- {
- lockObj = lockObjData[lockName];
- }
- else
- {
- lock (custLockObj)
- {
- if (lockObjData.ContainsKey(lockName))
- {
- lockObj = lockObjData[lockName];
- }
- else
- {
- // 如果获取不到锁,则创建一个锁对象
- lockObj = new ReaderWriterLockSlim();
- lockObjData[lockName] = lockObj;
- }
- }
- }
- return lockObj;
- }
- }
锁的封装 读写锁、lock的更多相关文章
- Linux 自旋锁,互斥量(互斥锁),读写锁
自旋锁(Spin Lock) 自旋锁类似于互斥量,不过自旋锁不是通过休眠阻塞进程,而是在取得锁之前一直处于忙等待的阻塞状态.这个忙等的阻塞状态,也叫做自旋. 自旋锁通常作为底层原语实现其他类型的锁. ...
- 多线程并发编程之显示锁ReentrantLock和读写锁
在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是 ...
- Go基础系列:互斥锁Mutex和读写锁RWMutex用法详述
sync.Mutex Go中使用sync.Mutex类型实现mutex(排他锁.互斥锁).在源代码的sync/mutex.go文件中,有如下定义: // A Mutex is a mutual exc ...
- Spring data Jpa,Mybatis,读写锁,@Lock 使用
Spring data jpa 支持注解式的读写锁(悲观锁),实际上这个东西硬编码也简单,但是基于Jpa 命名方式定义的Sql,只能用注解添加支持读写锁了, 不了解读写锁的可以点这里 mysql读写锁 ...
- JUC——线程同步锁(ReentrantReadWriteLock读写锁)
读写锁简介 所谓的读写锁值得是两把锁,在进行数据写入的时候有一个把“写锁”,而在进行数据读取的时候有一把“读锁”. 写锁会实现线程安全同步处理操作,而读锁可以被多个对象读取获取. 读写锁:ReadWr ...
- 架构师养成记--14.重入锁ReentrantLock 和 读写锁 ReentrantReadWriteLock
ReentrantLock 有嗅探锁定和多路分支等功能,其实就是synchronized,wait,notify的升级. this锁定当前对象不方便,于是就有了用new Object()来作为锁的解决 ...
- Go 互斥锁(sync.Mutex)和 读写锁(sync.RWMutex)
什么时候需要用到锁? 当程序中就一个线程的时候,是不需要加锁的,但是通常实际的代码不会只是单线程,所以这个时候就需要用到锁了,那么关于锁的使用场景主要涉及到哪些呢? 多个线程在读相同的数据时 多个线程 ...
- 从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解
同步自我的 csdn 博客 6.S081 从自旋锁.睡眠锁.读写锁到 Linux RCU 机制讲解_我说我谁呢 --CSDN博客 总结一下 O/S 课程里面和锁相关的内容. 本文是 6.S0 ...
- JAVA线程锁-读写锁
JAVA线程锁,除Lock的传统锁,又有两种特殊锁,叫读写锁ReadWriteLock 其中多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥 例子: /** * java线程锁分为读写锁 ReadWri ...
随机推荐
- Scala学习笔记之伴生对象
所谓伴生对象, 也是一个Scala中的单例对象, 使用object关键字修饰. 除此之外, 还有一个使用class关键字定义的同名类, 这个类和单例对象存在于同一个文件中, 这个类就叫做这个单例对象的 ...
- centos环境自动化批量安装软件脚本
自动化安装jdk软件部署脚本 准备工作: 1.在执行脚本的服务器上生成免密码公钥: 安装expect命令 yum install -y expect ssh-keygen 三次回车 2.将jdk-7u ...
- Mac Aria2 使用Privoxy将socks代理转化为http代理
安装Privoxy 打开终端安装privoxy来实现这里我是通过brew来进行的安装 brew install privoxy 看到这行已经安装成功 ==> Caveats To have la ...
- HTTPS 和 HTTP
https://www.zhihu.com/question/52790301
- NGUI缓动函数
缓动函数:http://easings.net/zh-cn 研究NGUI的博客:http://dsqiu.iteye.com/category/295721
- VBA 小知识
1. 循环 Dim i As Integer 'body Next 'body Wend 2. 键值数据结构 'create dictionary object Set dictMembers = C ...
- Host 'XXX' is not allowed to connect to this MySQL server 解决方案/如何开启MySQL的远程帐号
www.cnblogs.com/zhangzhu/archive/2013/08/22/3274831.html 如何开启MySQL的远程帐号-1)首先以 root 帐户登陆 MySQL 在 Wind ...
- String类的常用判断方法使用练习
选取了一些常用的判断方法进行了使用练习,后续跟新其他方法 package StringDemo; // String类的判断方法解析 // 1:boolean equals(); // 判断字符串是否 ...
- SQL Server创建复合索引时,复合索引列顺序对查询的性能影响
说说复合索引 写索引的博客太多了,一直不想动手写,有一下两个原因:一是觉得有炒剩饭的嫌疑,有兄弟曾说:索引吗,只要在查询条件上建索引就行了,真的可以这么暴力吗?二来觉得,索引是个非常大的话题,很难概括 ...
- C#获得客户端IP
代码: /// <summary> /// 获得当前页面客户端的IP /// </summary> /// <returns>当前页面客户端的IP</retu ...