解密Lazy<T>
1.Lazy<T>的使用
无意间看到一段代码,在创建对象的时候使用了Lazy,顾名思义Lazy肯定是延迟加载,那么它具体是如何创建对象,什么时候创建对象了? 先看这段示列代码:
public class OrderController : Controller
{
private readonly Lazy<OrderService> _orderSrv = new Lazy<OrderService>(); public ActionResult CreateOrder(OrderModel model)
{
var result = _orderSrv.Value.CreateOrder(model);
return Json(result);
}
}
使用非常简单,把 OrderService 放到Lazy<T> 中,然后 _orderSrv.Value 的时候才真正创建OrderService 对象。
那么问题来,是不是每次_orderSrv.Value 一下,就创建一个对象了? 想到这里,程序猿基本的条件反射,对着Lazy按下F12。
构造函数中,有个isThreadSafe的参数,默认是true。ok,参考了msdn的例子,我们来测试看看。
static void Main(string[] args)
{
Lazy<int> number = new Lazy<int>(() => Thread.CurrentThread.ManagedThreadId); Thread t1 = new Thread(() =>
Console.WriteLine("number on t1 = {0} ThreadID = {1}"
,number.Value, Thread.CurrentThread.ManagedThreadId));
t1.Start(); Thread t2 = new Thread(() =>
Console.WriteLine("number on t2 = {0} ThreadID = {1}"
,number.Value, Thread.CurrentThread.ManagedThreadId));
t2.Start(); Thread t3 = new Thread(() =>
Console.WriteLine("number on t3 = {0} ThreadID = {1}"
, number.Value,Thread.CurrentThread.ManagedThreadId));
t3.Start(); Console.ReadLine(); }
结果:
很明显,number 被ID=10的线程初始化后,值一直没有改变,说明三个线程用的是同一个实例。
再试试 isThreadSafe=false 。
Lazy<int> number = new Lazy<int>(() => Thread.CurrentThread.ManagedThreadId, false);
结果(1):
number实例被ID=11的线程使用后,其他线程就不能再正确使用了,number.value=0 说明 int并没有被赋值。
结果(2):
直接报错了,我的理解是,Lazy此时并不支持多线程并发。
2.Lazy<T> 的 valueFactory
继续在f12中找到解释:
结合我们上面的例子,可分析出,valueFactory是个委托,number.value的时候就是由valueFactory来创建这个实例。
看到这里,我们发现Lazy<T> 还是很强大的,可以用T的默认构造函数来创建实例也可以用指定的Func来创建实例,而且还支持多线程安全。
3.Lazy<T>的工作原理
用反编译插件看看代码:
static Lazy()
{
Lazy<T>.ALREADY_INVOKED_SENTINEL = () => default(T);
Lazy<T>.PUBLICATION_ONLY_SENTINEL = new object();
}
[__DynamicallyInvokable]
public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
{
if (valueFactory == null)
{
throw new ArgumentNullException("valueFactory");
}
this.m_threadSafeObj = Lazy<T>.GetObjectFromMode(mode);
this.m_valueFactory = valueFactory;
}
看到 default(T) 和 this.m_valueFactory = valueFactory 大概也知道是如何创建实例了吧。
本文博客园地址:http://www.cnblogs.com/struggle999/p/6917067.html
解密Lazy<T>的更多相关文章
- php blowfish加密解密具体算法
PHP Blowfish 算法的加密解密,供大家参考,具体内容如下<?php/*** php blowfish 算法* Class blowfish*/class blowfish{/*** b ...
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】
黑白图像直方图 发布时间: 2017年7月9日 18:30 最后更新: 2017年7月10日 21:08 时间限制: 1000ms 内存限制: 128M 描述 在一个矩形的灰度图像上,每个 ...
- [Spark內核] 第41课:Checkpoint彻底解密:Checkpoint的运行原理和源码实现彻底详解
本课主题 Checkpoint 运行原理图 Checkpoint 源码解析 引言 Checkpoint 到底是什么和需要用 Checkpoint 解决什么问题: Spark 在生产环境下经常会面临 T ...
- 3DES加解密 C语言
3DES(或称为Triple DES),它相当于是对每个数据块应用三次DES加密算法.3*8字节密钥. 设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代 ...
- js_md5加密和base64的加密解密
1.最近有些人在爬我们公司的数据,然有了这个md5加密的小需求.为什么叫小需求呢?嗯,之前没做过,会以为很复杂. 其实,是想多了. 2.前端md5加密,其实也并不是安全的,因为代码是可见的.也就是说, ...
- 实用工具类--第三方开源--Lazy
下载地址 :https://github.com/ddwhan0123/Lazy 工具 描述 AnimationUtils 动画工具类 AppUtils APP相关信息工具类 AssetDatabas ...
- CTF中编码与加解密总结
CTF中那些脑洞大开的编码和加密 转自:https://www.cnblogs.com/mq0036/p/6544055.html 0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到 ...
- CTF密码学常见加解密总结
CTF密码学常见加解密总结 2018年03月10日 19:35:06 adversity` 本文链接:https://blog.csdn.net/qq_40836553/article/details ...
- PHP的学习--RSA加密解密
PHP服务端与客户端交互或者提供开放API时,通常需要对敏感的数据进行加密,这时候rsa非对称加密就能派上用处了. 举个通俗易懂的例子,假设我们再登录一个网站,发送账号和密码,请求被拦截了. 密码没加 ...
随机推荐
- spring之注解
1.@Autowired 可以对成员变量.方法和构造函数进行自动配置(根据类型进行自动装配) public class UserImpl implements User { @Autowired pr ...
- sptt规范介绍
相关资源 如何开发sptt工程的原子操作 移动端测试方案--sptt sptt规范 一个标准的sptt工程的目录如下: [sptt-project] | -- [ios] | | -- [atoms] ...
- SIP DB33标准笔记 监控图像获取
实时监控图像的获取: a) 实时监控图像的获取过程应包括获取实时流.释放实时流.应使用 RFC 3261 中定义的方法INVITE 获取一个摄像机的实时监控视频流. 取消没有完成的连接应采用 CANC ...
- clamav 杀毒软件安装及使用配置
安装clamav 之前还需要安装zlib 要不然安装过程中会报错的. tar -zxvf zlib-1.2.3.tar.gz cd zlib-1.2.3 ./configure make make ...
- java多线程基本概述(二十)——中断
线程中断我们已经直到可以使用 interrupt() 方法,但是你必须要持有 Thread 对象,但是新的并发库中似乎在避免直接对 Thread 对象的直接操作,尽量使用 Executor 来执行所有 ...
- php 启动过程 - reqeust RSHUTDOWN 过程
php 启动过程 - reqeust RSHUTDOWN 过程 概述 request RSHUTDOWN 过程在请求结束后调用 调用触发 同 request RINIT 过程一样, 先是用 apach ...
- jQuery选择器与CSS选择器
1. 通过位置选择的几个操作: :first:默认情况下是相对整个页面来说的第一个,如:li:first表示整个页面的第一个li元素,而ul li:first表示整个页面的第一个li元素,并且是在ul ...
- JQuery 根据ID在页面中定位
1.锚点跳转简介 锚点其实就是可以让页面定位到某个位置上的点.在高度较高的页面中经常见到.比如百度的百科页面,wiki中的page内容. 我知道实现锚点的跳转有两种形式,一种是a标签+name属性:还 ...
- FileZilla可以连接但是传输文件失败
在linux本地创建文件夹后,用FileZilla传输文件失败了. 如果用的是普通用户,创建的文件夹是属于root用户.所以不能传输,没有权限. 修改权限:sudo chown -R lishengn ...
- hdu2196Computer 树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196 思路: 一看就是一道树形DP的题目,对于一个节点来说,到它的最远距离的路径可能来于子树,也可能来 ...