线程访问正在使用的变量

时间:2010-10-31 09:58:19

标签: c# thread-safety

我想知道,如果我有一个多核处理器并且我有多个线程,如果两个或多个线程同时访问一个变量,程序是否会崩溃?如何暂时阻止变量以便同时限制访问?

此致 Alexandru Badescu

4 个答案:

答案 0 :(得分:5)

它不会崩溃,但可能会产生错误的结果。

要阻止,您需要确保通过同一监视器上的锁定语句保护每个访问权限:

private readonly object monitor = new object();
private int sharedVariable;

public void MethodThatSetsVariable()
{
    lock (monitor)
    {
        sharedVariable = 5;
    }
}

public void MethodThatReadsVariable()
{
    int foo;
    lock (monitor)
    {
        foo = sharedVariable;
    }
    // Use foo now
}

备选方案:

  • 使用volatile变量,但volatile的确切行为很难理解。 (好吧,无论如何,它超出了我。)
  • 使用Interlocked
  • 上的方法

请注意,当它只是您感兴趣的单个共享变量时,这两个最适合。当您必须访问一组变量时,确保您只看到完全一致的状态,锁是最简单的方法。

另一种选择 - 如果可能的话,首选 - 是避免首先要求可变共享状态。它并不总是可能的,至少没有对消息传递架构进行彻底的重新设计 - 但是值得在可能的情况下进行瞄准。不可变类型有助于使这更容易实现。

答案 1 :(得分:2)

  

如果两个或多个线程同时访问变量,程序可能会崩溃

程序不太可能崩溃。它可能不会像你期望的那样表现,因为它会造成竞争条件。

  

如何暂时阻止变量以便同时限制多个访问

使用lock statement

答案 2 :(得分:2)

您可以使用lock关键字或Interlocked类。

e.g。

public class Foo
{
   private object barLock = new object();
   private int bar;

   public void Add(int x)
   {
        lock (barLock)
        {
            this.bar += x;
        }
   }
}

public class Foo
{
   private int bar;

   public void Increment()
   {
        Interlocked.Increment(ref x);
   }
}

我会尽可能使用Interlocked类,因为这通常是最简单,最有效(最快)的方法,但只能满足某些操作要求。对于更复杂的操作,lock是可行的方法。

我建议不要使用C#volatile关键字,因为这会影响对给定字段的所有访问权限。最好坚持更高级别的概念,例如lockInterlocked

答案 3 :(得分:1)

使用lock语句(这对于Monitor.Enter / Exit来说真的是语法糖)