创建对象线程新实例的静态方法是否安全?

Are static methods that creates a new instance of it's object thread safe?

根据我在其他 SO posts 上的阅读,我的猜测是 CreateTry1 和 CreateTry2 都不是线程安全的,但即使阅读了这么多,我仍然不能 100% 确定这是正确。

public ClassA
{
  private string MyString;

  private ClassA(string myString)
  {
    MyString = myString;
  }

  public static CreateTry1(string aString)
  {
    return new ClassA(aString);
  }

  public static CreateTry2(string aString)
  {
    ClassA a = new ClassA();
    a.MyString = aString;
    return a;
}

// The Below is not the main focus of the question
static public void Main(String[] args)
{
  Thread t1 = new Thread(p =>
  {
    int i = 0;
    while(i < 1000000)
    {
      ClassA newA = ClassA.CreateTry2("Hello");
      i++;
    }
  });

  Thread t2 = new Thread(p =>
  {
    int i = 0;
    while(i < 1000000)
    {
      ClassA newA = ClassA.CreateTry2("Hello");
      i++;
    }
  });

  t1.Start();
  t2.Start();
}

更多信息 1:澄清

我编辑了代码

这个问题专门针对 Selenium Grid。我想如果我能更好地理解什么是线程安全的,什么不是线程安全的(通常),那么我就会知道在 Selenium Grid(并行)中将代码重构为 运行 时应该避免什么不安全代码。但是,我想我跳进了游泳池的深水区,并不知道怎么在这里游泳,所以很抱歉。

我认为部分答案很简单,例如 "Non-Static variables (fields and properties) within a non-static class are Always thread safe. Static variables (fields and properties) inside a non-static or static class are not safe in general"。


更多信息 2:相关 SO posts

我读了很多post。有些陈述使事情变得清晰,而另一些则使事情变得更加混乱。

This comment made most sense。然而,声明的一部分说,"When your data in separate instances still gets mixed up, it's most likely because the data is not really separate." 似乎很难不看到你的一个变量(字段)是静态的,所以想知道在他不知情的情况下线程之间的数据交叉污染是如何发生的。

任何与以下 MSDN 声明相关的对话对我来说都没有完全意义:

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

1. About above quote

2. About above quote。这是一个很好的问题,但乍一看答案似乎过于复杂。我最终记得 'members' 指的是 class 中的字段、属性和方法(不仅仅是字段)。如此宽泛的陈述会使答案变得复杂。

以下 post、"Is this extension method thread safe" 是一个很好的问题,但我不知道哪个答案是正确的。我相信这两个 reposes 都是正确的,但 Avner 的回答非常笼统,而 Ondrej 的回答具体回答了这个问题。

一些posts,like this one, brought up the term 'shared state' which, after reading the following,似乎只不过是class中的静态字段(但我很容易出错)。

我不确定你想弄清楚什么,但我想知道两件事可能会有所帮助:

  • CreateTry1CreateTry2 不访问共享数据。 MyString 属性 不在实例之间共享。所以这些方法是线程安全的。
  • 构造函数保证是线程安全的。 ClassA 的多个并行实例不会相互干扰,即线程安全。

Are static methods that creates a new instance of it's object thread safe?

没有。这不是线程安全的充分必要条件。

以此作为你问题的反例:

public class Foo
{
    public int Value;
    private Foo()
    {
        this.Value = magic;
    }
    private static int magic = 42;
    public static Foo CreateFooIncrement()
    {
        magic += 1;
        return new Foo();
    }
    public static Foo CreateFooDecrement()
    {
        magic -= 1;
        return new Foo();
    }   
}

根据对 CreateFooIncrementCreateFooDecrement.

的并发调用,Foo 的实例当然有可能被意外地 Value 创建

此示例 class Foo 具有创建其自身实例的静态方法 class,并且绝对不是线程安全的。