这对静态类和线程安全来说是不好的做法吗?

时间:2009-03-13 18:55:25

标签: c# thread-safety

假设我没有使用锁定语句,这是一种不好的做法吗?

public static class Foo
{
  public static string Bar()
  {
    bool working;

    while (working)
    {
      // Loop until ready to run.
    }

    working = true;

    // Do stuff here.

    working = false;
    return "done."
  }
}

编辑 -

在尝试这样的事情之后,我意识到这有几个原因是不可行的。我只是好奇..我发布的例子甚至没有用。

6 个答案:

答案 0 :(得分:4)

循环是一个CPU消耗过程。

我的意思是,如果你所做的一切只是在等待。这不是一件好事。

答案 1 :(得分:4)

首先,工作对方法是私有的,所以它不起作用。调用它的2个线程将各自拥有自己的“工作”。你需要让它成为一个静态场来产生效果。

即使这样,你也可以获得竞争条件。 2个线程可以同时命中,通过while(工作)条件,然后设置working = true;并且同时做事。

使用锁或信号量有助于解决此问题。

答案 2 :(得分:2)

假设您的意思是working将从另一个线程修改,则存在两个问题:

  1. 您应该成为volatile static成员。易失性将告诉编译器不要在优化中尝试任何“聪明”的东西。

  2. 你写过了所谓的“自旋锁”。在某些特殊情况下,这是最好的方法。但通常这是一个糟糕的主意,因为在设置working变量之前,您的线程会占用CPU。

答案 3 :(得分:1)

是的,这是不好的做法。

为什么不使用lock语句?查看Monitor类,我可以提供互斥和同步。

不应使用旋转循环和非线程安全变量。

答案 4 :(得分:1)

还有另一个问题,如果工作对多个线程可见(如另一张海报所提到的,它是一个局部变量),正如现在所写,不能保证系统中的其他内核会看到更新工作在正确的顺序。需要一个内存屏障,例如System.Threading.Thread.MemoryBarrier,以保证CPU不会通过“在这里做东西”重新排序写入工作。

但你应该考虑使用锁而不是。无锁编程难以理解。

答案 5 :(得分:0)

使用锁定是防止并发问题的唯一方法(其他不做的事情)。

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

  public static string Bar()
  {
    lock (barLock)
    {
      // Do work
      return "Done";
    }
  }
}