MSpec:如何使静态变量线程安全?

我正在使用MSpec作为我的最新项目,总的来说我对它非常满意。 但是,当我的测试以并行方式运行时,我确实遇到并发问题,我想知道是否有人遇到过这个问题,或者更好的是,有一个解决方案?

MSpec严重依赖静态方法和变量来工作。

现在,当我在我的基类中定义静态变量时,它会被多个测试类使用,并且我在paralel中运行我的测试,它们共享相同的静态变量,从而干扰彼此。

我正在使用NCrunch和Resharper作为我的测试人员,我遇到了两个问题。

有人熟悉这个问题吗?

首先,我建议阅读MSDN上的Thead安全指南 。 这将使您很好地了解如何以及为什么在C#中使方法线程安全。

以下规则概述了实现线程的设计准则:

  • 避免提供改变静态的静态方法。 在常见的服务器方案中,静态状态在请求之间共享,这意味着多个线程可以同时执行该代码。 这开启了线程错误的可能性。 考虑使用将数据封装到不在请求之间共享的实例的设计模式。
  • …添加锁以创建线程安全的代码会降低性能,增加锁争用,并且可能会发生死锁错误
  • 请注意锁定部分中的方法调用。 当类A中的静态方法调用类B中的静态方法时,可能会导致死锁,反之亦然。 如果A和B都同步它们的静态方法,这将导致死锁。 你可能会在严重的线程压力下发现这种僵局。
  • 请注意lock语句的问题(Visual Basic中的SyncLock)。 使用lock语句解决所有线程问题很诱人。 但是,System.Threading.Interlocked类对于必须是primefaces的更新来说是优越的…

作为一般说明,我更喜欢使用的方法(如果可能)是使方法(静态或其他) 不可变 。 为此,所有变量都应该是本地的(在堆栈上本地创建,或作为参数传递给方法)。 通过确保仅使用局部变量,或者成员变量是不可变的,每个线程将在其自己的隔离区中操作,对变量的更改不会影响另一个线程。 这是我在.NET仿真软件中广泛使用的一种方法,允许在C#中实现无锁且因此高性能的multithreading。

或者,如果变量必须是成员变量,则可以通过锁定关键字保护对它们的可变访问。 小心使用锁将导致上下文切换(减速)并引入死锁情况的可能性。 它也不保证线程安全,因为使用锁必须防止您试图阻止的特定方案。

为了进一步阅读,我建议查看这些描述C#中线程安全性和不变性的相关问题:

  • 设计Thread Safe类
  • 实现线程安全
  • 为什么不可变对象是线程安全的

最好的祝福,

默认情况下,静态字段不是线程安全的。 为了使它们成为线程安全的,您可以使用[ThreadStatic]属性来修饰它们。

有关详细信息,请查看MSDN上的ThreadStaticAttribute类 。