2010-09-13 174 views
6

静态类中静态变量的问题。静态类中的静态属性

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

回答

11

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

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

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

+3

严格来说,静态类没有* instance *,但每个静态字段都有一个副本 – 2010-09-13 10:24:24

+0

您是对的。感谢您的额外信息。我已经更新了我的答案。 – 2010-09-13 10:26:13

+0

@Marc:是的,但是...... OP *做了*(令人困惑地)说,“这个变量的值是为这个类的所有实例设置的吗?“所以我猜测OP实际上只是有一个普通的课程,并且正在谈论一个静态属性,要么是这个或者误用了”实例“这个词。 – 2010-09-13 10:42:40

2

只是添加到讨论中(为什么不?):是的,一个static属性在类的所有实例中共享,而不管线程如何(除非后备字段标记为ThreadStatic,即!)。但是,是的,在处理这些属性时,您必须面对潜在的多线程问题。以下是我认为其他人正在研究的情景。

考虑以下代码:

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

前面的是其中的竞争条件可能会导致两个线程执行的是应该是两个不可分割的动作很简单的例子,而是最终有效地被一个动作。

举例说明:

 
Thread 1      Thread 2 
int x = MyClass.StaticProperty;         // Let's say 
           int x = MyClass.StaticProperty; // this is 1. 
MyClass.StaticProperty = x + 1;         // OK, so x is 
           MyClass.StaticProperty = x + 1; // now... 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