有关静态类中静态变量的问题。
如果我有一个静态类并且在其中设置了一个属性的值,那么公开暴露,是为该类的所有实例设置的该变量的值吗?因此,如果线程1将property的值设置为999,那么是否也为线程2设置了值999?
答案 0 :(得分:12)
是的,确实如此。 AppDomain中只有一个静态类'字段的副本。
但是,您应该考虑同步。如果线程1设置(写入)变量并且线程2同时读取它,则可能会得到意外的结果,因为一个写操作实际上可能被分成多个处理器指令。
假设您设置了long
的值。这是64位值,写入至少包含2个处理器指令(在32位机器上)。从理论上讲,可能会在两条写指令之间调度相同的long
变量,从而导致意外行为。
答案 1 :(得分: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
。