使用.NET Lazy <t>的线程安全单例实现似乎因XUnit而失败

时间:2016-09-06 11:10:59

标签: c# multithreading

我有一个类HashSet<T>,它不是线程安全的,我想通过使用lock语句来保证线程安全。

public sealed class DatabaseContextResolver
{
    #region Constructors

    DatabaseContextResolver()
    {
        _registeredContexts = new Hashtable();
    }

    #endregion

    #region Properties

    static readonly object ReadWriterLock = new object();

    static readonly Lazy<DatabaseContextResolver> DatabaseContextResolverInstantiator = new Lazy<DatabaseContextResolver>(() => new DatabaseContextResolver());

    internal static DatabaseContextResolver Instance => DatabaseContextResolverInstantiator.Value;

    readonly Hashtable _registeredContexts;

    #endregion

    #region Methods

    public void RegisterContext<TContext>(TContext context, string contextName)
        where TContext : class
    {
        context.ThrowIfNull(new MongoMigrationContextException("The context to register should not be null."));

        var namedContextTypeDependency = new NamedTypeDependency(contextName, typeof(TContext), context);

        if (_registeredContexts.ContainsKey(namedContextTypeDependency.ToString()))
        { throw new MongoMigrationDependencyException("The context cannot be registered because it's already registered.");  }

        lock (ReadWriterLock)
        {
            if (!_registeredContexts.ContainsKey(namedContextTypeDependency.ToString()))
            { _registeredContexts.Add(namedContextTypeDependency.ToString(), namedContextTypeDependency); }
            else
            { throw new MongoMigrationDependencyException("The context cannot be registered because it's already registered."); }
        }
    }

    internal void Clear()
    {
        _registeredContexts.Clear();
    }

    #endregion
}

使用Lazy<T>使此类成为线程安全的,因此我确信在给定时间只存在一个实例。这个假设是否正确?

我有一个clear()方法可以清除HashSet<T>中的项目。 现在,我确实有几个xUnit测试,它们会向这个类添加项目。

这是通过以下代码完成的:

DatabaseContextResolver.Instance.RegisterContext(this, contextName);

当我在xUnit中运行所有测试时,它们中的某些测试失败了,因为HashSet<T>中具有相同键的项目已经存在?

我认为我的实现是线程安全的吗?

每个xUnit类(包含影响此问题的多个测试)都会实现IDisposable并调用clear()方法。

0 个答案:

没有答案