4

阅读后,LazyInitializer 它是:

它提供了另一种初始化模式,有多个线程竞相初始化。

这是一个示例:

Expensive _expensive;
public Expensive Expensive
     {
       get // Implement double-checked locking
         {
           LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());
           return _expensive;
         }
     }

问题 #1

看着 : 在此处输入图像描述

为什么#A 说它实现了双重检查锁定?它只是一个获得财产?

问题2

#B(lambda 表达式)是线程安全的吗?

问题 #3

所以我通过查看样本搜索了这个“种族初始化”的事情:

volatile Expensive _expensive;
public Expensive Expensive
{
  get
  {
    if (_expensive == null)
    {
      var instance = new Expensive();
      Interlocked.CompareExchange (ref _expensive, instance, null);
    }
    return _expensive;
  }
}

然后我想:初始化不是种族是线程安全的吗?

e/g/ 如果有 2 个线程进入:

在此处输入图像描述

昂贵的对象将被创建两次!

再说一次,3个问题

1)为什么#A说它实现了双重检查锁定?它只是一个获得财产?

2)#B(l​​ambda 表达式)是线程安全的吗?

3)初始化不是线程安全的

4

1 回答 1

5

有各种重载EnsureInitialized。有些接受一个synclock对象(可以null并且将由该EnsureInitialized方法创建)。其他人没有 asynclock作为参数。所有EnsureInitialized保证如果在对象未初始化时由两个(或更多)不同的线程同时调用,这两个线程将收到对同一对象的引用。所以:

Expensive _expensive;

// On thread 1
LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());

// On thread 2
LazyInitializer.EnsureInitialized (ref _expensive,() => new Expensive());

_expensive两个线程将看到的对象将是相同的。

唯一的问题是它new Expensive()可以被调用两次(每个线程一次,所以在多线程竞争中它可以被调用更多次。)

如果您不想要它,请使用synclock重载:

Expensive _expensive;
object _sync = null;
bool _useless;

// On thread 1
LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive());

// On thread 2
LazyInitializer.EnsureInitialized (ref _expensive, ref useless, ref _sync, () => new Expensive());

现在new Expensive(),对于运行的两个(或更多)线程的每种可能组合,将只调用一次。

于 2012-07-19T07:59:26.457 回答