いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

.NET クラスライブラリ探訪-022 (System.ThreadStaticAttribute)(スレッドローカルストレージ, TLS, GetData, SetData, LocalDataStoreSlot)


前回、スレッドのデータスロットについて記述しましたが、実際にGetDataやSetDataを利用して
スロットを使うよりも、以下の属性を利用する方がパフォーマンスなどの点で推奨されています。

System.ThreadStaticAttribute


ThreadStatic属性はstaticなフィールドに付与します。
通常のstatic変数は、各スレッドにて共有されるデータですが、
この属性が付与されているフィールドは、各スレッドにて固有の値を持つ事ができるようになります。
(つまり、データスロットと同じ状態になります。)


尚、MSDNに記載されているとおり、この属性を付与したフィールドは初期化してはいけません。


以下、サンプルです。

#region ThreadStaticAttributeSamples-01
    public class ThreadStaticAttributeSamples01 : IExecutable{

        private class ThreadState{

            /// <summary>
            /// 各スレッド毎に固有の値を持つフィールド.
            /// </summary>
            [ThreadStatic]
            static KeyValuePair<string, int> NameAndId;
            /// <summary>
            /// 各スレッドで共有されるフィールド.
            /// </summary>
            static KeyValuePair<string, int> SharedNameAndId;

            public static void DoThreadProcess(){
                Thread thread = Thread.CurrentThread;

                //
                // ThreadStatic属性が付加されたフィールドと共有されたフィールドの両方に値を設定.
                //
                NameAndId       = new KeyValuePair<string, int>(thread.Name, thread.ManagedThreadId);
                SharedNameAndId = new KeyValuePair<string, int>(thread.Name, thread.ManagedThreadId);

                Console.WriteLine("[BEFORE] ThreadStatic={0} Shared={1}", NameAndId, SharedNameAndId);

                //
                // 他のスレッドが動作できるようにする.
                //
                Thread.Sleep(TimeSpan.FromMilliseconds(200));

                Console.WriteLine("[AFTER ] ThreadStatic={0} Shared={1}", NameAndId, SharedNameAndId);
            }
        }

        public void Execute(){

            List<Thread> threads = new List<Thread>();
            for(int i = 0; i < 5; i++){
                Thread thread = new Thread(ThreadState.DoThreadProcess);

                thread.Name         = string.Format("Thread-{0}", i);
                thread.IsBackground = true;

                threads.Add(thread);

                thread.Start();
            }

            threads.ForEach(thread => { thread.Join(); });
        }
    }
#endregion

================================
過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。