2012-01-18 23 views
4

我为我的最新项目使用了MSpec,总体而言,我非常满意。但是,当我的测试以并列方式运行时,我确实遇到并发问题,我想知道是否有人遇到了这个问题,或者更好的解决方案?MSpec:如何使静态变量线程安全?

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

现在看来,当我在我的基类中定义了多个测试类使用的静态变量,并且我以平行方式运行我的测试时,它们共享相同的静态变量,从而干扰了彼此。

我正在使用NCrunch和Resharper作为我的testrunner,并且遇到了这两个问题。

任何人都熟悉这个问题?

+0

是不是像http:// sta一样ckoverflow.com/questions/1254750/i-need-to-create-a-thread-safe-static-variable-in-c-sharp-net? – PKeidel 2012-01-18 09:46:03

+0

你可以请一个简单的例子/复制。我想将其包含在我们的示例中。谢谢! – 2012-01-19 11:43:58

回答

0

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

查看ThreadStaticAttribute Class at MSDN了解更多信息。

+3

ThreadStatic为每个线程创建一个独立的静态字段,这严格地说与线程安全不同,确保每个调用者都可以安全地调用静态字段。我建议使用静态属性,并在get和set方法中确保线程安全 – hcb 2012-01-18 09:34:33

1

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

以下规则概述执行线程设计准则:

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

作为一般的纸条,我更喜欢使用的方法(如果可能)是使一个方法(静态或以其他方式)immutable。要做到这一点,所有变量应该是本地的(在堆栈上本地创建,或作为参数传递给方法)。通过确保只使用局部变量,或者成员变量不可变,每个线程将在其自己的隔离区中运行,并且更改为变量不会影响另一个线程。这是我在.NET仿真软件中广泛使用的一种方法,可以在C#中实现无锁且高性能的多线程处理。

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

进一步的阅读我建议看这些相关的问题,这说明线程安全性和不变性在C#:

最好的问候,