靜態字段被類的所有實例所共享,即此類的所有實例都訪問同一內存地址。 所以該內存位置的值變更的話,這種變更對所有的實例都可見。
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()); }
如果靜態字段是一個非托管資源,會怎么樣呢?