【问题标题】:Why are static fields generally considered threadsafe?为什么静态字段通常被认为是线程安全的?
【发布时间】:2012-01-25 00:04:05
【问题描述】:

我是一名 .NET 和 Java 开发人员,对线程比较陌生。我想知道为什么静态字段、静态构造函数等通常被认为是“线程安全的”。

例如,在 .NET 中构造单例时,使其成为线程安全的技巧之一是使模式的某些组件成为静态的。

如果我的上述任何假设不正确,请告诉我。

【问题讨论】:

  • 您从哪里读到将静态内容设为线程安全?
  • 有点相关的帖子stackoverflow.com/q/1090650/758280。
  • 我不了解 C# 和 .net,但在 java 中,静态字段并不比任何其他类型的字段线程安全。
  • 来自 Jeffrey 的链接:Static methods aren't inherently thread-safe. They're treated no differently by the CLR than instance methods. The difference is that one should generally try to make them thread-safe
  • 你倒退了。 由于可能从多个线程访问静态字段和方法,因此确保它们是线程安全的工作是一种很好的编程习惯。 这就是为什么您会看到这么多文档说“静态这个类的方法是线程安全的,其余的都不是”。

标签: c# java .net multithreading


【解决方案1】:

我认为您会感到困惑,这些“技巧”不是关于线程,而是避免线程初始化。因此,如果在应用程序加载时初始化了某些内容,您不必担心线程在首次请求资源时必须初始化事物,从而避免哪个线程首先到达那里的竞争条件

【讨论】:

    【解决方案2】:

    您的上述假设是不正确的。静态字段并不比任何其他字段更线程安全。

    即使在创建单例时,指示对象已经构建的标志/指针/项也必须由同步原语保护,如果有可能被多个线程同时调用。

    您对单例使用静态(类级别)变量的原因是您只需要该类的一个对象。使用对象级变量将限制您每个 object 一个对象,而不是每个类一个对象,每个对象一个对象,嗯,只是一个常规对象 :-)

    【讨论】:

      【解决方案3】:

      静态构造函数(大部分)是线程安全的,因为运行时在运行它们之前会获得一个锁,从而提供同步。不过,重入仍然是个问题。

      至于“通常被认为是线程安全的静态字段”,我只能说普遍的智慧来自少数白痴,他们因为找不到专业开发人员的工作而获得了教学工作,现在将其传递给对一群从未有机会学习得更好的学生来说是白痴。

      【讨论】:

      • class fff { public static readonly int five = 5; } 的线程安全是什么?
      • @Royi:这更线程安全,因为它是readonly,而不是因为它是static。 (但是请参阅我对克里斯的回答的 cmets,即使您的示例也不是完全线程安全的)
      • 删除只读会使其不是线程安全的吗?您是说一个线程在初始化之前可以看到默认值吗?
      • @RoyiNamir:不,我说的是数据竞争,一个线程在另一个线程写入的同时更改值。例如,如果 five 被修改,if (five < array.Length) return array[five]; 可以抛出 IndexOutOfBoundsException。
      • 这是应该通过 lock 保护的方法代码。我问的只是有值的字段
      【解决方案4】:

      静态字段本质上不是线程安全的——这是一个谬误。静态实际上与线程无关。它只是意味着该字段与一个类型相关联,而不是一个类型的实例。关于静态的线程安全唯一需要注意的是它们通常由静态构造函数设置,并且通常是只读的,例如:

      class Foo {
          // You can safely read `five` from any thread
          public static readonly  int five = 5; 
      }
      

      但是,这不会以任何方式使对象本身成为线程安全的。这个集合没有任何线程安全的:

      class Foo {
          // You still need to take a lock before writing to this list and probably while reading from it
          public static readonly List<Int> myList = new List<Int>; 
      }
      

      【讨论】:

      • 好吧,即使 readonly 在值类型的字段上也不能保证线程安全。
      • No- 只是意味着一旦它被设置,没有其他人会写入它,所以你不能在它上面得到“脏读”
      • 当然可以。如果构造函数启动一个线程,或者将this 存储在另一个线程可以读取的位置,然后分配该字段。
      • 我不确定我是否遵循 - 在您的示例中 this 是什么?这是一个静态的
      • 对于静态 readonly 值,问题是重入(正如我在回答中提到的)。我只是不希望有人认为他们不会使用static 来神奇地解决线程问题,而是使用readonly。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-04
      • 2023-03-04
      • 1970-01-01
      相关资源
      最近更新 更多