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.

posted @ 2019-09-26 10:19 YamatAmain 阅读(458) 评论(0) 推荐(0) 编辑
摘要: 1. swagger .Net Core 3.0中的swagger,必须引用5.0.0 及以上版本。可以在Nuget官网查看版本。目前最新版本(2019 9 25) 5.0.0rc3 Install Package Swashbuckle.AspNetCore.Swagger Version 5.0 阅读全文
posted @ 2019-09-25 11:16 YamatAmain 阅读(328) 评论(0) 推荐(0) 编辑
摘要: `redis memcache key value redis`,在网上看了一些这方面的资料,有三种观点: 1. 读写内存比 快 2. 读写内存比 快 3. 读写内存比 快,但是redis整体性能优于 所以我做了一下测试. redis的测试结果 第一次 root@ubuntu:/home/yamat 阅读全文
posted @ 2018-09-06 11:25 YamatAmain 阅读(697) 评论(0) 推荐(0) 编辑
摘要: 距离上一篇博文,差不多两年了。终于憋出来了一篇。[手动滑稽] List是c 中很常见的一种集合形式,近期在阅读c 源码时,发现了一个很有意思的定义: c var list = new List(); Console.WriteLine(list.Capacity); c static readonl 阅读全文
posted @ 2017-11-16 14:20 YamatAmain 阅读(1087) 评论(8) 推荐(5) 编辑
摘要: 如何基于Microsoft.Owin.Security.OAuth,使用Client Credentials Grant授权方式给客户端发放access token? Client Credentials Grant的授权方式就是只验证客户端(Client),不验证用户(Resource Own... 阅读全文
posted @ 2015-12-08 16:24 YamatAmain 阅读(10109) 评论(16) 推荐(12) 编辑
摘要: Newtonsoft.json是一款不错的序列化反序列化第三方组件,具体如何使用属于基础知识,此处不再讲解.看以下代码: public class OutgameEntity{ public string orderid{get;set;} public DateTime? payTime { get; set; }}很简单的一个实体类假如此时有一个url:http://www.xxx.xx/do.svc/xxx?data=,我们如果要把OutgameEntity实体类的值传过去,就需要反序列化对象为string字符串.public static string JsonSeria... 阅读全文
posted @ 2013-12-31 16:29 YamatAmain 阅读(9513) 评论(4) 推荐(9) 编辑
摘要: 我从事手机app服务端开发现在已经是3个年头,自己也整理出了一套相对好用的服务架构,写出来,跟大家一起分享。如有不足,还请多指教。 一:基础流程图。 其实有一点还需要加上,就是对json的压缩和加密,一来给用户节约流量,二来防止请求被截取破解我们的参数。具体先压缩后加密还是先加密后压缩这个问题看需求 阅读全文
posted @ 2013-06-09 16:38 YamatAmain 阅读(102553) 评论(17) 推荐(12) 编辑
摘要: 如果想做一个分布式系统,肯定需要不同的机器来提供不同的服务,而有些基于http协议,有些tcp/ip协议,有些使用MSMQ通道,以往的技术实现起来比较容易,但是有一点是致命的:管理起来不方便。于是WCF顺势而出。但是使用一段时间后你会发现,你只是需要一点点,但是却有一堆臃肿的东西在你服务器上,于是wcfrest和WebApi顺势而出(其实是很原始的技术,只是换了一个马甲,重新封装了一下)。基础东西我就不介绍,主要说下实际应用的东西。 写博客一段时间,偶然百度下自己写的内容,发现各种爬虫把自己码的字都爬过去了。好吧,你赢了。此片博文特此感谢小蓝同学。好基友你们懂的。 Interface的定义.. 阅读全文
posted @ 2013-06-05 23:05 YamatAmain 阅读(3546) 评论(7) 推荐(5) 编辑
摘要: 并行编程看似简单,但是其实要设计一个较完美的解决方案是很复杂的。可能由于神秘的错误,程序并不能如预期那样运行。从今天起,我打算每星期更新一次关于并行编程方面的文章。 在Net4.0中引入了一种新的编程模型,极大简化了并行编程的难度和工作。后台使用了高效的登山算法等保证效率。此外,NET4.0中还包含调试和分析的工具,方便我们更好的掌握并行编程。 1:任务(Task) 任务是协同工作的一系列顺序操作,他们共同完成一个更大的操作。我们在构建并行程序时,要确定任务的粒度,这有助于硬件的有效利用。如果选择太小,任务管理的开销占主要,如果太粗,可能会失去并行的机会,因为... 阅读全文
posted @ 2013-05-04 20:51 YamatAmain 阅读(1480) 评论(0) 推荐(1) 编辑
摘要: 一:安装Nodejs1:在官网(http://nodejs.org/)下载 node-v0.8.15.tar.gz(我下载的是0.8.4版本)2:ctrl+alt+T打开终端,找到这个包,然后解压。tar zxvf node-v0.8.15.tar.gz3:cd node-v0.8.4 4:./configure5:make6:sudo install make安装完成后,验证是否安装成功,输入node –v好像新版本的nodejs自带npm,输入npm –v二:安装Express1:npm install express –g(如果出现Error,请用root登录)ubuntu的root账号 阅读全文
posted @ 2012-12-01 22:58 YamatAmain 阅读(3729) 评论(1) 推荐(0) 编辑
点击右上角即可分享
微信分享提示