【问题标题】:Static properties in static classes静态类中的静态属性
【发布时间】:2010-09-13 10:17:33
【问题描述】:

关于静态类中的静态变量的问题。

如果我有一个静态类并在其中设置一个属性的值,公开暴露,这个变量的值是否为该类的所有实例设置?那么如果线程 1 将属性的值设置为 999,那么线程 2 的值是否也设置为 999?

【问题讨论】:

    标签: c# static


    【解决方案1】:

    是的,是的。 AppDomain 中的静态类字段只有一份副本。

    但是,您应该考虑同步。如果线程 1 设置(写入)变量并且线程 2 同时读取它,您可能会得到意想不到的结果,因为一个写入操作实际上可能被划分为多个处理器指令。

    假设您设置了long 的值。这是一个 64 位值,写入它涉及至少 2 个处理器指令(在 32 位机器上)。从理论上讲,可能会在两个写入指令之间安排读取相同的long 变量,从而导致意外行为。

    【讨论】:

    • 严格来说,没有静态类的instance,但是每个静态字段都有一个副本
    • 你是对的。感谢您提供更多信息。我已经更新了我的答案。
    • @Marc:是的,但是...... OP 确实 说(令人困惑),“这个变量的值是为类的所有实例设置的吗?”所以我猜 OP 实际上只有一个常规类,并且正在谈论一个静态属性。要么是这样,要么是误用了“实例”这个词。
    【解决方案2】:

    只是为了补充讨论(为什么不呢?):是的,static 属性在类的所有实例之间共享,无论线程如何(除非支持字段标记为ThreadStatic,即!)。但是,是的,在处理此类属性时,您必须面对潜在的多线程问题。这是我认为其他人正在处理的情况。

    考虑这段代码:

    int x = MyClass.StaticProperty;
    MyClass.StaticProperty = x + 1;
    

    前面是一个非常简单的示例,说明竞争条件可能导致两个线程执行假定两个不可分割的操作,但实际上最终成为一个单独的操作。

    举例说明:

    线程 1 线程 2 int x = MyClass.StaticProperty; // 比方说 int x = MyClass.StaticProperty; // 这是 1。 MyClass.StaticProperty = x + 1; // 好的,所以 x 是 MyClass.StaticProperty = x + 1; // 现在... 2.

    你看到问题了吗?两个线程可能在任一线程写入 之前都读取 属性的值;并且写入的值取决于读取的值,这对于两个线程都是相同的!

    在像上面这样的简单场景中,System.Threading 命名空间中提供了一个方便的类,它可以使多线程读/写相当轻松地实现:Interlocked。例如,要以线程安全的方式增加上面的StaticProperty,您可以按如下方式更新MyClass

    class MyClass
        static int _staticProperty;
        public static int StaticProperty
        {
            get { return _staticProperty; }
        }
    
        public static int IncrementProperty()
        {
            // increments _staticProperty ATOMICALLY
            // and returns its previous value
            return Interlocked.Increment(_staticProperty);
        }
    }
    

    在更复杂的情况下(即,当您不是简单地以直接的方式修改纯数字字段时),您可能需要设计自己的同步策略,其中最常见的是有一个指定的锁对象,并且简单地lock 用于您想要以原子方式执行的每个操作。

    【讨论】:

      猜你喜欢
      • 2014-09-10
      • 2021-08-26
      • 2011-06-11
      • 2015-08-13
      • 2018-04-18
      • 2014-01-29
      • 2012-10-15
      • 2013-08-17
      相关资源
      最近更新 更多