今天在知乎上看到一個問題【為什麼在同一進程中創建不同線程,但線程各自的變數無法線上程間互相訪問?】。在多線程中,每個線程都是獨立運行的,不同的線程有可能是同一段代碼,但不會是同一作用域,所以不會共用。而共用記憶體,並沒有作用域之分,同一進程內,不管什麼線程都可以通過同一虛擬記憶體地址來訪問,不同進程也可 ...
今天在知乎上看到一個問題【為什麼在同一進程中創建不同線程,但線程各自的變數無法線上程間互相訪問?】。在多線程中,每個線程都是獨立運行的,不同的線程有可能是同一段代碼,但不會是同一作用域,所以不會共用。而共用記憶體,並沒有作用域之分,同一進程內,不管什麼線程都可以通過同一虛擬記憶體地址來訪問,不同進程也可以通過ipc等方式共用記憶體數據。全局變數:任何線程都可以訪問;局部變數(棧變數):任何線程執行到該函數時均可訪問,函數外不可訪問;線程變數:每個線程只能訪問自己的那個拷貝,其他線程不可見。今天就用C#來實現同一段代碼的不同線程,全局變數、局部變數、線程變數。
瞭解進程與線程
什麼是多任務,簡單來說就是操作系統同時可以運行多個任務。例如:一遍聽歌,一遍寫文檔等。多核CPU可以執行多任務,但是單核CPU也可以執行多任務,CPU是順序執行的,操作系統讓任務輪流執行,例如:聽歌執行一次,停頓0.01s,寫文檔執行一次,停頓0.01s等等。由於CPU的執行速度很快,我們感覺就像所有的任務都是同時執行。對操作系統來說,一個任務就是一個進程,一個進程至少有一個線程。進程是資源分配的最小單位,線程是CPU調度的最小單位。
普通的程式寫法
private static List<int> data = Enumerable.Range(1, 1000).ToList(); public static void SimpleTest() { for (int i = 0; i < 10; i++) { List<int> tempData = new List<int>(); foreach (var d in data) { tempData.Add(d); } Console.WriteLine($"i:{i},合計:{data.Sum()},是否相等:{data.Sum() == tempData.Sum()}"); } Console.WriteLine("單線程運行結束"); }
多線程寫法
private static List<int> data = Enumerable.Range(1, 1000).ToList(); public static async Task MoreTaskTestAsync() { List<Task> tasks = new List<Task>(); for (int i = 0; i < 10; i++) { var tempi = i; var t = Task.Run(() => { List<int> tempData = new List<int>(); foreach (var d in data) { tempData.Add(d); } Console.WriteLine($"i:{tempi},合計:{data.Sum()},是否相等:{data.Sum() == tempData.Sum()}"); }); tasks.Add(t); } await Task.WhenAll(tasks); //或者Task.WaitAll(tasks.ToArray()); Console.WriteLine("多線程運行結束"); }
不同的線程同一段代碼,但不會是同一作用域,所以tempData數據沒有互相影響。
全局變數:data,多個線程都可以訪問,list只讀的時候是線性安全
局部變數:i就是局部變數,訪問的線程可以訪問,去掉【var tempi = i;】,運行結果列印出來,值都是一樣的,增加的都是每個線程都訪問單獨的tempi變數
i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True i:10,合計:500500,是否相等:True
線程變數:tempData,每個線程只訪問自己的,互不影響,運行結果
i:3,合計:500500,是否相等:True i:6,合計:500500,是否相等:True i:0,合計:500500,是否相等:True i:1,合計:500500,是否相等:True i:4,合計:500500,是否相等:True i:2,合計:500500,是否相等:True i:7,合計:500500,是否相等:True i:5,合計:500500,是否相等:True i:8,合計:500500,是否相等:True i:9,合計:500500,是否相等:True
寫多線程的時候需要註意,變數的作用域,否則程式運行出來的結果將不會是想要的結果,註意,註意變數作用域。