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

时间:2012-01-18 09:12:07

标签: c# unit-testing bdd mspec

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

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

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

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

有谁熟悉这个问题?

2 个答案:

答案 0 :(得分:1)

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

  

以下规则概述了实施线程的设计指南:

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

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

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

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

致以最诚挚的问候,

答案 1 :(得分:0)

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

有关详细信息,请查看ThreadStaticAttribute Class at MSDN

相关问题