今回は、System.Threading.ThreadLocal
ThreadLocal
ThreadStatic属性と同じく、スレッドローカルストレージ(TLS)を定義するために利用します。
以前のバージョンから存在するThreadStatic属性については、以下の記事を参照ください。
- .NET クラスライブラリ探訪-022 (System.ThreadStaticAttribute)(スレッドローカルストレージ, TLS, GetData, SetData, LocalDataStoreSlot)
従来より存在していたThreadStatic属性は、以下の点が行えませんでした。
- インスタンスフィールドには対応していない。(staticフィールドのみ) (インスタンスフィールドにも属性を付与することが出来るが、ちゃんと動作しない)
- フィールドの値は常に、その型のデフォルト値で初期化される。初期値を設定しても無視される。
ThreadLocal
つまり
- インスタンスフィールドに対応している。
- フィールドの値を初期値で初期化出来る。
利用方法は、System.Lazyと似ており、コンストラクタに初期化のためのデリゲートを渡します。
ThreadLocal<int> _id = new ThreadLocal<int>(() => Thread.CurrentThread.ManagedThreadId);
valueFactoryに指定した値は遅延評価され、それぞれのスレッドの最初のアクセス時に評価されます。
以下サンプルです。
#region ThreadLocalSamples-01 /// <summary> /// ThreadLocal<T>クラスのサンプルです。 /// </summary> public class ThreadLocalSamples01 : IExecutable { #region Static Fields // ThreadStatic [ThreadStatic] static int count = 2; static ThreadLocal<int> count2 = new ThreadLocal<int>(() => 2); #endregion #region Fields [ThreadStatic] int count3 = 2; ThreadLocal<int> count4 = new ThreadLocal<int>(() => 4); #endregion public void Execute() { // // ThreadLocal<T>は、.NET 4.0から追加された型である。 // ThreadStatic属性と同様に、スレッドローカルストレージ(TLS)を表現するための型である。 // // 従来より存在していたThreadStatic属性には、以下の点が行えなかった。 // ・インスタンスフィールドには対応していない。(staticフィールドのみ) // (インスタンスフィールドにも属性を付与することが出来るが、ちゃんと動作しない) // ・フィールドの値は常に、その型のデフォルト値で初期化される。初期値を設定しても無視される。 // // ThreadLocal<T>は、上記の点を解決している。つまり // ・インスタンスフィールドに対応している。 // ・フィールドの値を初期値で初期化出来る。 // // 利用方法は、System.Lazyと似ており、コンストラクタに初期化のためのデリゲートを渡す。 // // // staticフィールドのThreadState属性の確認 // ThreadStatic属性では、初期値を宣言時に設定していても無視され、強制的にデフォルト値が適用されるので // 出力される値は、全て0となる。 // int numberOfParallels = 10; using (var countdown = new CountdownEvent(numberOfParallels)) { for (var i = 0; i < numberOfParallels; i++) { int tmp = i; new Thread(() => { Console.WriteLine("ThreadStatic [count]>>> {0}", count++); countdown.Signal(); }).Start(); } countdown.Wait(); } // // staticフィールドのThreadLocal<T>の確認 // ThreadLocal<T>は、初期値を設定できるので、出力される値は2となる。 // using (var countdown = new CountdownEvent(numberOfParallels)) { for (var i = 0; i < numberOfParallels; i++) { new Thread(() => { Console.WriteLine("ThreadLocal<T> [count2]>>> {0}", count2.Value++); countdown.Signal(); }).Start(); } countdown.Wait(); } // // インスタンスフィールドのThreadStatic属性の確認 // ThreadStatic属性は、インスタンスフィールドに対しては効果が無い。 // なので、出力される値は2,3,4,5,6...とインクリメントされていく. // using (var countdown = new CountdownEvent(numberOfParallels)) { for (var i = 0; i < numberOfParallels; i++) { int tmp = i; new Thread(() => { Console.WriteLine("ThreadStatic [count3]>>> {0}", count3++); countdown.Signal(); }).Start(); } countdown.Wait(); } // // インスタンスフィールドのThreadLocal<T>の確認 // ThreadLocal<T>は、インスタンスフィールドに対しても問題なく利用できる。 // なので、出力される値は4となる。 // using (var countdown = new CountdownEvent(numberOfParallels)) { for (var i = 0; i < numberOfParallels; i++) { new Thread(() => { Console.WriteLine("ThreadLocal<T> [count4]>>> {0}", count4.Value++); countdown.Signal(); }).Start(); } countdown.Wait(); } count2.Dispose(); count4.Dispose(); } } #endregion
以下、実行結果です。
ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadStatic [count]>>> 0 ThreadLocal[count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadLocal [count2]>>> 2 ThreadStatic [count3]>>> 2 ThreadStatic [count3]>>> 3 ThreadStatic [count3]>>> 4 ThreadStatic [count3]>>> 5 ThreadStatic [count3]>>> 6 ThreadStatic [count3]>>> 7 ThreadStatic [count3]>>> 8 ThreadStatic [count3]>>> 9 ThreadStatic [count3]>>> 10 ThreadStatic [count3]>>> 11 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4 ThreadLocal [count4]>>> 4
ThreadLocal
以下、参考資料です。
- ThreadLocal
クラス - ThreadStaticAttribute クラス
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場