线程安全延迟实例化使用MEF [英] Thread-Safe lazy instantiating using MEF

查看:255
本文介绍了线程安全延迟实例化使用MEF的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

// Member Variable
private static readonly object _syncLock = new object();

// Now inside a static method

foreach (var lazyObject in plugins)
{
   if ((string)lazyObject.Metadata["key"] = "something")
   {
      lock (_syncLock)
      {
         // It seems the `IsValueCreated` is not up-to-date
         if (!lazyObject.IsValueCreated) 
            lazyObject.value.DoSomething();
      }
      return lazyObject.value;
   }
}



在这里,我需要同步每个循环的访问。有许多线程迭代这个循环,并根据,他们正在寻找,一个懒惰的实例被创建并返回。

Here I need synchronized access per loop. There are many threads iterating this loop and based on the key they are looking for, a lazy instance is created and returned.

lazyObject 不应该创建更多的一次。虽然类是这样做的,尽管所使用的锁,在高线程我有多个实例创建的(我跟踪这个用互锁.Increment 挥发性 静态INT 和地方记录它)。问题是我没有获得的 MEF 定义定义如何使用懒人类创建对象。我应该注意 CompositionContainer中在一个已经使用的构造线程安全的选择。

lazyObject should not be created more that one time. Although Lazy class is for doing so and despite of the used lock, under high threading I have more than one instance created (I track this with a Interlocked.Increment on a volatile static int and log it somewhere). The problem is I don't have access to definition of Lazy and MEF defines how the Lazy class create objects. I should notice the CompositionContainer has a thread-safe option in constructor which is already used.

我的问题:

1)为什么锁不起作用?

1) Why the lock doesn't work ?

2)我应该使用锁的阵列,而不是性能改进一把锁?

2) Should I use an array of locks instead of one lock for performance improvement ?

推荐答案

T的默认构造函数在你的复杂? MEF使用 LazyThreadSafetyMode.PublicationOnly 这意味着每个线程访问unitialised 将生成一个新( ) T 直到第一次完成初始化。然后,该值返回为被丢弃当前访问的所有线程 .value的和自己的新()实例。如果你的构造是复杂的(也许做得太多?),你应该重新定义为做最少的建设工作和移动配置的另一种方法。

Is the default constructor of T in your Lazy complex? MEF uses LazyThreadSafetyMode.PublicationOnly which means each thread accessing the unitialised Lazy will generate a new() on T until the first to complete the initialisation. That value is then returned for all threads currently accessing .Value and their own new() instances are discarded. If your constructor is complex (perhaps doing too much?) you should redefine it as doing minimal construction work and moving configuration to another method.

您需要思考的方法作为一个整体。如果你考虑:

You need to think about the method as a whole. Should you consider:

public IPlugin GetPlugin(string key)
{
  mutex.WaitOne();

  try
  {
    var plugin = plugins
      .Where(l => l.Metadata["key"] == key)
      .Select(l => l.Value);
      .FirstOrDefault();

    return plugin;
  }
  finally
  {
    mutex.ReleaseMutex();
  }
}

您还需要考虑,如果插件不是只读的,那么你需要同步访问该实例太多,否则很可能在另一个线程上进行修改,从而导致你的代码摔倒。

You also need to consider that if plugins is not read-only then you need to synchronise access to that instance too, otherwise it may be modified on another thread, causing your code to fall over.

这篇关于线程安全延迟实例化使用MEF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆