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.

最新文章

  1. 立即执行函数表达式(IIFE)
  2. Filter过滤器简单应用( 接口访问控制 )
  3. JUC回顾之-CyclicBarrier底层实现和原理
  4. Notepad++隐藏的用法
  5. python知识点(07-08)
  6. 使用visual studio测试功能进行暴力破解
  7. Oracle 数据库表空间碎片查询和整理
  8. 测来测去,感觉REQUESTS最实在
  9. 关于 linux ssh 的配置.
  10. sticker.js贴纸效果
  11. Ubuntu下使用rpm 软件包
  12. 如何使用EF优雅的配置一对一的关系
  13. Javascript中获取浏览器类型和操作系统版本等客户端信息常用代码
  14. 【翻译】Ext JS 6.2 早期访问版本发布
  15. Android Service详解
  16. BugFix:URL or HTTP headers are too long (IP=127.0.0.1)
  17. 将sqlserver导出的csv数据导入到ubuntu和mac上的mysql
  18. iOS----------关于Cornerstone的偏好设置
  19. Orchard详解--第一篇 介绍
  20. undo丢失恢复异常恢复,运维DBA反映Oracle数据库无法启动报错ORA-01157 ORA-01110,分析原因为Oracle数据库坏块导致

热门文章

  1. [转]UIpath advanced certification dumps
  2. MySQL 社区版 安装小记
  3. Android框架式编程之ViewModel
  4. 学习之Redis(二)
  5. 选择IT公司的雇主提问
  6. 基于django的个人博客网站建立(五)
  7. 【Linux命令】setfacl、getfacl命令基本用法(文件权限全文控制列表acl)
  8. Linux系统:Centos7下搭建ClickHouse列式存储数据库
  9. goweb-搭建服务
  10. Java分布式系统---消息中间件