锁的概念,这里不作详细阐述。先从最经典的应用场景来讲,单例模式在不考虑静态构造函数实现的方式下,用锁实现是必须的。好比:html
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)是最优雅的使用方式。this
ReaderWriterLockSlim支持三种锁定模式
1. Read
2. Write
3. UpgradeableRead
这三种锁定模式所对应的方法分别是:
1. EnterReadLock
2. EnterWriteLock
3. EnterUpgradeableReadLock线程
其中,Read模式是共享锁定模式,任意线程均可以在此模式下同时得到锁。
Write模式是互斥模式,任意数量线程只容许一个线程进入该锁。code
其实这篇博文的目的,就是为了测试传统Object_lock 和ReaderWriteLockSlim的性能差别。废话很少,实现上使用了赵姐夫的CodeTimerhtm
测试代码以下:对象
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); } }
使用控制台应用程序blog
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.