【軟體開發、系統開發、程式開發】多執行緒多任務存取相同變數,隔離保留各自任務的值 ThreadLocal 技術講解
在講解幾篇關於多工、多執行緒、平行作業的技術文章後,想來談談另外一個深入的關鍵多多執行緒的問題,那就是多執行緒(多工)作業模式下,如何存取相同變數值,而且又希望各自的執行緒對相同變數又有各自的“值”。
在 .Net 技術平台下,有個 ThreadLocal<T> 的泛型類別,這個類別可以專門用於有多個執行緒需要共同存取一個變數,但每個執行緒對這個變數的值,又個別記錄隔離儲存,互不影響。我舉個例子來說明,有執行緒A、執行緒B、執行緒C、執行緒D,這四個執行緒平行作業,將共同存取一個變數 X ,但在執行緒A存取變數X時,設定值為 10;執行緒B存取變數X時,設定值為 20;執行緒C存取變數X時,設定值為 30;執行緒D存取變數X時,設定值為 40; 在執行緒A設定 X變數值為 10時,並不會影響到 執行緒 B/C/D 各自設定的 X 變數值。
一樣在此,我透過一個程式範例來進行實例說明,這個專案類型就簡單用 Console 控制台類型來引導…
完整程式碼如下:
namespace NetQna.Demo
{
/// <summary>
/// ThreadLocal 示範教學(網智數位-軟體開發)
/// </summary>
public class Program
{
/// <summary>
/// 所有執行緒共同存取的變數值
/// </summary>
static ThreadLocal<int> X = new ThreadLocal<int>();
static void ExecThreadTask(object obj)
{
ThreadEntity currThread = (ThreadEntity)obj;
//在各自的執行緒環境設定 X 變數值,觀察各自的執行緒下,X 變數值各自記錄
X.Value = currThread.ThreadValue;
//顯示出 目前所在的執行緒 的值
Console.WriteLine($"現在的執行緒 ID:{Thread.CurrentThread.ManagedThreadId},{nameof(X)}變數值為:{X.Value}。");
//顯示出 目前所在的執行緒 的值
Console.WriteLine($"現在的執行緒 名稱:{currThread.ThreadName},{nameof(X)}變數值為:{X.Value}。");
Console.WriteLine();
}
static void Main(string[] args)
{
Dictionary<string, int> threadABCD = new Dictionary<string, int> { { "A", 10 }, { "B", 20 }, { "C", 30 }, { "D", 40 } };
//分別啟動 A、B、C、D 執行緒,並執行 存取 X 變數值
foreach (var t in threadABCD)
{
ThreadEntity obj = new ThreadEntity { ThreadName = t.Key, ThreadValue = t.Value };
//Action<string, int> action = ExecThreadTask(t.Key, t.Value);
Thread currThread = new Thread(ExecThreadTask);
currThread.Start(obj);
//這邊我刻意停頓 1 秒,以利顯示各自執行緒
Thread.Sleep(1000);
}
Console.Read();
X.Dispose(); //X 變數 釋放
}
public class ThreadEntity
{
public string ThreadName { get; set; }
public int ThreadValue { get; set; }
}
}
}
程式說明講解

一開始我宣告一個屬性變數為 X ,也就是今天講解主要的類別 ThreadLocal,
待會就是用 這個 X 變數,來讓所有執行緒進行存取設定 X 變數值。
宣告一個帶有 object 參數的方法,待會就是要讓所有執行緒去各自執行這個方法,這個方法主要我將 object 型態 的 參數 obj 轉型為我自己宣告的類別 ThreadEntity 類別(PS:因為 Thread 建構子對應的方法的參數只能是 object 型態,所以我透過轉型來避開這限制)。
public class ThreadEntity
{
public string ThreadName { get; set; }
public int ThreadValue { get; set; }
}
最關鍵的地方,我在這個方法設定了各自執行緒要對應的 X 變數值
//在各自的執行緒環境設定 X 變數值,觀察各自的執行緒下,X 變數值各自記錄
X.Value = currThread.ThreadValue;
我這邊分別建立 A、B、C、D 四個執行緒,然後分別設定他們待會要指定 X 變數的值為(10、20、30、40)。
程式執行結果如下圖
可以看出 A、B、C、D執行緒各自維護自己 X 變數的值。
參考文章 C#多工作業與平行處理技術講解
1.透過 Thread 類別撰寫多執行緒多工作業。
2.透過 Delegate 委託支援的方法,撰寫非同步任務。
3-1.透過 Parallel 類別操控多任務平行作業(一)。
3-2. 透過 Parallel 類別操控多任務平行作業(二)。
4.使用 Task 自行控制非同步任務作業。
5.在非同步作業時,如何取消非同步任務。
6.多執行緒多任務存取相同變數,但卻各自隔離保留各自任務的值。
7.非同步存取變數的問題。
8.非同步資源鎖定解決方式。
網智數位-軟體開發(軟件開發)
針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
公司電話:02-55991310
公司地址(業務營運處):台北市中山區錦州街 25 號 5 樓
skype: netqna
line:netqna
微信:netqna
黃先生 Allen
沒有留言:
張貼留言
如您對本文有任何建議或意見,歡迎您留下您寶貴的意見!