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中的并发锁的更多相关文章

  1. Redis学习笔记~Redis并发锁机制

    回到目录 redis客户端驱动有很多,如ServiceStack.Redis,StackExchange.Redis等等,下面我使用ServiceStack.Redis为例,介绍一下在redis驱动中 ...

  2. 如何理解Java中眼花缭乱的各种并发锁?

    在互联网公司面试中,很多小伙伴都被问到过关于锁的问题. 今天,我给大家一次性把Java并发锁的全家桶彻底讲明白.包括互斥锁.读写锁.重入锁.公平锁.悲观锁.自旋锁.偏向锁等等等等.视频有点长,大家一定 ...

  3. Java并发指南8:AQS中的公平锁与非公平锁,Condtion

    一行一行源码分析清楚 AbstractQueuedSynchronizer (二) 转自https://www.javadoop.com/post/AbstractQueuedSynchronizer ...

  4. Redis修改数据多线程并发—Redis并发锁

    本文版权归博客园和作者本人吴双共同所有 .转载爬虫请注明地址,博客园蜗牛 http://www.cnblogs.com/tdws/p/5712835.html 蜗牛Redis系列文章目录http:// ...

  5. WCF初探-28:WCF中的并发

    理解WCF中的并发机制 在对WCF并发机制进行理解时,必须对WCF初探-27:WCF中的实例化进行理解,因为WCF中的并发特点是伴随着服务实例上下文实现的.WCF的实例上下文模型可以通过Instanc ...

  6. linux设备驱动第五篇:驱动中的并发与竟态

    综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被 ...

  7. Python中的并发编程

    简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态.打开文件列表.追踪指令执行情况的程序指针以及一个保存局部变量的调用栈.通常情况下,一个进程依照一个单序列控制流顺序执 ...

  8. 在 Java 中高效使用锁的技巧--转载

    竞争锁是造成多线程应用程序性能瓶颈的主要原因 区分竞争锁和非竞争锁对性能的影响非常重要.如果一个锁自始至终只被一个线程使用,那么 JVM 有能力优化它带来的绝大部分损耗.如果一个锁被多个线程使用过,但 ...

  9. java高并发锁的3种实现

    初级技巧 - 乐观锁 乐观锁适合这样的场景:读不会冲突,写会冲突.同时读的频率远大于写. 以下面的代码为例,悲观锁的实现: Java代码   public Object get(Object key) ...

随机推荐

  1. AndroidStudio配置好了so文件运行却报错 java.lang.UnsatisfiedLinkError:

    报错截图: 解决方法:在app的build.gradle 下的defaultConfig里面添加过滤即可: ndk { abiFilters 'armeabi' //兼容x86cpu架构 需要什么样的 ...

  2. tp、tftp、nfs--服务器搭建

    服务器 1. ftp服务器 1.1检查是否安装 vsftpd -version 1.2 安装 sudo apt-get install vsftpd 1.3卸载 sudo apt-get remove ...

  3. Mac中 pip3 install mysqlclient 报错

    主要错误提示如下: ld: library not found for -lssl clang: error: linker command failed with exit code 1 (use ...

  4. September 08th, 2019. Sunday, Week 37th.

    A heavy drew refreshed the earth at night. 夜晚厚重的露水滋养着大地. From Leo Tolstoy. Today is the White Drew D ...

  5. 【tf.keras】tensorflow datasets,tfds

    一些最常用的数据集如 MNIST.Fashion MNIST.cifar10/100 在 tf.keras.datasets 中就能找到,但对于其它也常用的数据集如 SVHN.Caltech101,t ...

  6. SpringBoot2.0 整合 SpringSecurity 框架,实现用户权限安全管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Security简介 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方 ...

  7. spring常用注解整理

    参看大佬博客https://www.cnblogs.com/xiaoxi/p/5935009.html

  8. [转]Sumifs函数多条件求和的9个实例

    本文转自:http://m.officezhushou.com/sumif/5187.html 第一部分:sumifs函数用法介绍 excel中sumifs函数是Excel2007以后版本新增的多条件 ...

  9. GO 全面解析 json tag 篇

    在处理json格式字符串的时候,经常会看到声明struct结构的时候,属性的右侧还有反引号括起来的内容.形如: type User struct { UserId int `json:"us ...

  10. Redis之高可用、集群、云平台搭建(非原创)

    文章大纲 一.基础知识学习二.Redis常见的几种架构及优缺点总结三.Redis之Redis Sentinel(哨兵)实战四.Redis之Redis Cluster(分布式集群)实战五.Java之Je ...