locker

  • 使用过双检索来实现 单例模式
  1. private static object lockingObject = new object();
  2. public static LazySample InstanceCreation()
  3. {
  4. if(lazilyInitObject == null)
  5. {
  6. lock (lockingObject)
  7. {
  8. if(lazilyInitObject == null)
  9. {
  10. lazilyInitObject = new LazySample ();
  11. }
  12. }
  13. }
  14. return lazilyInitObject ;
  15. }
  • 那现在这种写法已经太low了,完全可以用 Lazy<T> 来替换使用,它是一个线程安全,懒实现的方式,参考如下代码
  1. public sealed class Singleton
  2. {
  3. private static readonly Lazy<Singleton> instanceHolder =
  4. new Lazy<Singleton>(() => new Singleton());
  5. private Singleton()
  6. {
  7. ...
  8. }
  9. public static Singleton Instance
  10. {
  11. get { return instanceHolder.Value; }
  12. }
  13. }

Lazy<T>

Lazy<T> 一个很好的真实示例是使用 ORM(对象关系映射器),例如 Entity Framework 和 NHibernate。

假设您有一个实体 Customer,它具有 Name、PhoneNumber 和 Orders 属性, Name 和 PhoneNumber 是常规的字符串类型,但 Orders 是一个导航属性,它返回的是 Customer 曾经下过的成百上千的订单。

你可能经常想要查看所有客户的信息并获取他们的 Name 和 Phoneumber 来给他们打电话。这是太普通不过的业务需求了,但想象一下,如果你每次获取客户都把和他相关的上千条订单给拉出来的话,其实这些订单你目前是不需要的,这就是完全的浪费资源!

理想的场景 Order 应该是延迟加载,除非你确实需要它们

  • Lazy<T> 确实非常好用,可以让你更加专注于业务,少写一些累赘代码,但本质上它的底层是用 lock 实现的,参考如下代码
  1. private void ExecutionAndPublication(LazyHelper executionAndPublication, bool useDefaultConstructor)
  2. {
  3. lock (executionAndPublication)
  4. {
  5. if (_state == executionAndPublication)
  6. {
  7. if (useDefaultConstructor)
  8. {
  9. ViaConstructor();
  10. }
  11. else
  12. {
  13. ViaFactory(LazyThreadSafetyMode.ExecutionAndPublication);
  14. }
  15. }
  16. }
  17. }