静态字段被类的所有实例所共享,即此类的所有实例都访问同一内存地址。 所以该内存位置的值变更的话,这种变更对所有的实例都可见。
class MyClass { int number = 1; static int staticNumber = 10; public void SetValue(int value1, int value2) { this.number = value1; staticNumber = value2; } public string DisplayValues() { return string.Format("number:{0}, staticNumber:{1}", this.number, staticNumber); } }
class Program { static void Main(string[] args) { MyClass class1 = new MyClass(); MyClass class2 = new MyClass(); class1.SetValue(2, 20); Console.WriteLine("Values in class1 are: {0}", class1.DisplayValues()); class2.SetValue(3, 30); Console.WriteLine("Values in class2 are: {0}", class2.DisplayValues()); // 再次显示 class1 实例,发现 staticNumber 的值是 30. Console.WriteLine("Values in class1 are: {0}", class1.DisplayValues()); } }
进一步,如果有多个线程同时访问静态字段,并对其赋值,那么会出现什么样的情况呢?
(由于进程是一组资源,而进程中的多个线程会共享进程中的资源。)
实际操作发现,对int 字段的访问非常快,不会出现资源抢夺问题。
public class Worker { // Volatile is used as hint to the compiler that this data member will be accessed by multiple threads. private volatile bool shouldStop; private MyClass class3 = new MyClass(); // This method will be called when the thread is started. public void DoWork() { while (!shouldStop) { Console.WriteLine("Worker thread: working and setting values."); class3.SetValue(3, 30); } Console.WriteLine("Worker thread: terminating gracefully..."); } public void RequestStop() { this.shouldStop = true; } }
static void Main(string[] args) { MyClass class1 = new MyClass(); MyClass class2 = new MyClass(); class1.SetValue(1, 10); Console.WriteLine("Values in class1 are: {0}", class1.DisplayValues()); class2.SetValue(2, 20); Console.WriteLine("Values in class2 are: {0}", class2.DisplayValues()); // 再次显示 class1 实例,发现 staticNumber 的值是 20. Console.WriteLine("Values in class1 are: {0}", class1.DisplayValues()); // Create the thread object. Worker worker1 = new Worker(); Thread workerThread = new Thread(worker1.DoWork); // Start the worker thread. workerThread.Start(); // Loop until worker thread acivates. while (!workerThread.IsAlive) ; // Put the main thread to sleep for a while to allow worker thread do some work. Thread.Sleep(5); // Set values by main thread. class1.SetValue(10, 100); Console.WriteLine("Values in class1 are: {0}", class1.DisplayValues()); // Request the worker thread to stop. worker1.RequestStop(); // Use the Join method to block the current thread until the object's thread terminates. workerThread.Join(); Console.WriteLine("Main thread: Worker thread has terminated."); Console.WriteLine("Values in class1 are: {0}", class1.DisplayValues()); }
如果静态字段是一个非托管资源,会怎么样呢?