Net中的并发锁
object _lock
锁的概念,这里不做详细阐述。先从最经典的应用场景来说,单例模式在不考虑静态构造函数实现的方式下,用锁实现是必须的。比如:
public class Singleton
{
private static Singleton _Singleton = null;
private static object Singleton_Lock = new object();
public static Singleton CreateInstance()
{
if (_Singleton == null)
{
lock (Singleton_Lock)
{
if (_Singleton == null)
{
_Singleton = new Singleton();
}
}
}
return _Singleton;
}
}
这里我们注意到
static object Singleton_Lock = new object()
这里的lock,其实是一个语法糖,具体定义就不多说,也不是本文的重点。简单说一下lock的注意事项
1. lock的对象必须是引用类型(string类型比较特殊,会被CLR‘暂留’,所以也不行)
2. lock推荐使用静态、私有、只读的对象。
3. 对于2中的只读,是需要保证在lock外无法修改。也补充了第一点中string类型不行的原因。
4. lock(this),如果无法保证外部及其他线程是否会访问,最好不要这样。因为可能会发生死锁。
综上,lock(readonly static referenceTypes)是最优雅的使用方式。
Net3.5中的ReaderWriterLockSlim
ReaderWriterLockSlim支持三种锁定模式
1. Read
2. Write
3. UpgradeableRead
这三种锁定模式所对应的方法分别是:
1. EnterReadLock
2. EnterWriteLock
3. EnterUpgradeableReadLock
其中,Read模式是共享锁定模式,任意线程都可以在此模式下同时获得锁。
Write模式是互斥模式,任意数量线程只允许一个线程进入该锁。
其实这篇博文的目的,就是为了测试传统Object_lock 和ReaderWriteLockSlim的性能差异。废话不多,实现上使用了赵姐夫的CodeTimer
测试代码如下:
public class MemoryCache<TKey, TValue>
{
private ConcurrentDictionary<TKey, TValue> _dicCache = new ConcurrentDictionary<TKey, TValue>();
private Dictionary<TKey, Lazy<TValue>> _dicLazyValue = new Dictionary<TKey, Lazy<TValue>>();
private ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();
private object _locker = new object();
public TValue GetValueByObjectLocker(TKey key, Lazy<TValue> value)
{
if (!_dicLazyValue.ContainsKey(key))
{
lock (_locker)
{
if (!_dicLazyValue.ContainsKey(key))
{
_dicLazyValue.Add(key, value);
}
}
}
if (_dicCache == null)
{
lock (_locker)
{
if (_dicCache == null)
{
_dicCache = new ConcurrentDictionary<TKey, TValue>();
}
}
}
return _dicCache.GetOrAdd(key, _dicLazyValue[key].Value);
}
public TValue GetValueByLockSlim(TKey key, Lazy<TValue> value)
{
if (!_dicLazyValue.ContainsKey(key))
{
try
{
_cacheLock.EnterWriteLock();
if (!_dicLazyValue.ContainsKey(key))
{
_dicLazyValue.Add(key, value);
}
}
finally
{
_cacheLock.ExitWriteLock();
}
}
if (_dicCache == null)
{
try
{
_cacheLock.EnterUpgradeableReadLock();
if (_dicCache == null)
{
_dicCache = new ConcurrentDictionary<TKey, TValue>();
}
}
finally
{
_cacheLock.ExitUpgradeableReadLock();
}
}
return _dicCache.GetOrAdd(key, _dicLazyValue[key].Value);
}
}
使用控制台应用程序
static void Main(string[] args)
{
MemoryCache<string, string> _memoryCache = new MemoryCache<string, string>();
CodeTimer.Initialize();
CodeTimer.Time("object lock", 1000, () =>
{
var lazyStr = new Lazy<string>(() => Thread.CurrentThread.ManagedThreadId.ToString());
_memoryCache.GetValueByObjectLocker("123", lazyStr);
});
CodeTimer.Time("LockSlim", 1000, () =>
{
var lazyStr = new Lazy<string>(() => Thread.CurrentThread.ManagedThreadId.ToString());
_memoryCache.GetValueByLockSlim("456", lazyStr);
});
System.Console.WriteLine("123");
System.Console.ReadLine();
}
结果:
object lock
Time Elapsed: 7ms
CPU Cycles: 6,414,332
Gen 0: 0
Gen 1: 0
Gen 2: 0
LockSlim
Time Elapsed: 1ms
CPU Cycles: 3,182,178
Gen 0: 0
Gen 1: 0
Gen 2: 0
综上,当下次有使用'锁'的时候,请优先考虑ReaderWriterLockSlim以获取更高的性能和更低的CPU Cycles.
Net中的并发锁的更多相关文章
- Redis学习笔记~Redis并发锁机制
回到目录 redis客户端驱动有很多,如ServiceStack.Redis,StackExchange.Redis等等,下面我使用ServiceStack.Redis为例,介绍一下在redis驱动中 ...
- 如何理解Java中眼花缭乱的各种并发锁?
在互联网公司面试中,很多小伙伴都被问到过关于锁的问题. 今天,我给大家一次性把Java并发锁的全家桶彻底讲明白.包括互斥锁.读写锁.重入锁.公平锁.悲观锁.自旋锁.偏向锁等等等等.视频有点长,大家一定 ...
- Java并发指南8:AQS中的公平锁与非公平锁,Condtion
一行一行源码分析清楚 AbstractQueuedSynchronizer (二) 转自https://www.javadoop.com/post/AbstractQueuedSynchronizer ...
- Redis修改数据多线程并发—Redis并发锁
本文版权归博客园和作者本人吴双共同所有 .转载爬虫请注明地址,博客园蜗牛 http://www.cnblogs.com/tdws/p/5712835.html 蜗牛Redis系列文章目录http:// ...
- WCF初探-28:WCF中的并发
理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过Instanc ...
- linux设备驱动第五篇:驱动中的并发与竟态
综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被 ...
- Python中的并发编程
简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态.打开文件列表.追踪指令执行情况的程序指针以及一个保存局部变量的调用栈.通常情况下,一个进程依照一个单序列控制流顺序执 ...
- 在 Java 中高效使用锁的技巧--转载
竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...
- java高并发锁的3种实现
初级技巧 - 乐观锁 乐观锁适合这样的场景:读不会冲突,写会冲突.同时读的频率远大于写. 以下面的代码为例,悲观锁的实现: Java代码 public Object get(Object key) ...
随机推荐
- CODING 祝大家中秋快乐!
- Python装饰器(Decorators )
http://book.pythontips.com/en/latest/decorators.html 在<Built-in Functions(3.6)>和<Python上下文管 ...
- 运维工程师必会工具(Nmap和TCPdump)
1.NMap工具 主要功能:探测主机是否在线.扫描主机开放端口和嗅探网络服务,用于网络探测和安全扫描. NMap支持很多扫描技术,例如:UDP.TCPconnect().TCPSYN(半开扫描).ft ...
- AXN文档
https://help.aliyun.com/document_detail/59705.html?spm=a2c4g.11186623.6.664.58a053afCvMM57 AXN api文档 ...
- 20191214 Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4)
概述 切了 ABCE,Room83 第一 还行吧 A - Happy Birthday, Polycarp! 题解 显然这样的数不会很多. 于是可以通过构造法,直接求出 \([1,10^9]\) 内所 ...
- 记录自己的一次pjax性能优化
什么是pjax? pjax = ajax + pushState 通过ajax让页面进行局部刷新,然后通过pushstate让url发生改变,再让pushState,让页面产生一个回退的记录,从而让页 ...
- Flutter中高级培训
Flutter中高级培训 一.简介 Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面.Flutter可以与现有的代码一起工作.本课程全面介绍Flutter ...
- idea中导入别人的vue项目并运行
1. 下载node.js 在搭建vue的开发环境之前,先下载node.js,下载地址:https://nodejs.org/en/ https://blog.csdn.net/antma/articl ...
- win7安装centos7虚拟机
1. 场景描述 因测试中需要linux集群,目前的服务器不太方便部署,需要本机(windows7)启动多个linux虚拟机,记录下,希望能帮到需要的朋友. 2. 解决方案 2.1 软件准备 (1)使用 ...
- Unity ugui屏幕适配与世界坐标到ugui屏幕坐标的转换
我们知道,如今的移动端设备分辨率五花八门,而开发过程中往往只取一种分辨率作为设计参考,例如采用1920*1080分辨率作为参考分辨率. 选定了一种参考分辨率后,美术设计人员就会固定以这样的分辨率来设计 ...