知識マップ: マルチスレッドの実務ベストプラクティス .NET編 ── スレッドを増やす前に決めておくこと
記事「マルチスレッドの実務ベストプラクティス .NET編 ── スレッドを増やす前に決めておくこと」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。
マルチスレッドが持ち込む問題は、実行順で結果が変わる競合状態と、互いのロックを待ち合うデッドロックの2種類です。競合は複数スレッドと共有可変状態が揃ったときにだけ起きるので、正しく同期するより先に同期が必要な場所を減らすのが設計の背骨になります。.NETではスレッドを自作せずTPLとスレッドプールに乗り、データ並列はParallel.For系に任せます。ただし1反復が軽いループは並列化のオーバーヘッドで逆に遅くなり、反復同士を待ち合わせるコードはデッドロックします。共有はスレッドローカル状態への分割やチャネルでの受け渡しで減らし、残った共有だけを専用ロックオブジェクトで守り、複数ロックの取得順序を統一します。停止はCancellationTokenによる協調キャンセルが唯一の正解で、Thread.Abortは.NET 5以降では実行時例外になります。UIは作成したスレッドの専有物で、別スレッドからはInvokeやDispatcher経由で依頼します。
flowchart LR
accTitle: .NETのマルチスレッド設計ベストプラクティスの知識マップ
accDescr: 共有可変状態が競合状態を生む構図と、スレッドを自作せずTPLとスレッドプールに乗ること、分割・キューでの受け渡しによる共有の削減、ロックの規律とデッドロック対策、協調キャンセルによる停止設計、UIスレッドへの依頼という4原則の関係を示す図
race_condition["競合状態(race condition)"]
shared_mutable_state["共有可変状態"]
lock_ordering["ロック取得順序の統一"]
deadlock["デッドロック(deadlock)"]
monitor_tryenter["Monitor.TryEnter(タイムアウト付き)"]
task_parallel_library["TPL(Task Parallel Library)"]
manual_thread_creation["スレッドの自作(new Thread)"]
managed_thread_pool["マネージドスレッドプール"]
asynchronous_io["非同期I/O"]
parallel_for["Parallel.For / Parallel.ForEach"]
parallel_overhead["並列化のオーバーヘッド"]
thread_local_state["スレッドローカル状態"]
channel_t["Channel<T>"]
backpressure["backpressure"]
blockingcollection["BlockingCollection<T>"]
concurrent_collection["スレッドセーフなコレクション型"]
dedicated_lock_object["専用ロックオブジェクト"]
lock_statement["lockステートメント"]
plain_await["plain await"]
semaphoreslim["SemaphoreSlim"]
interlocked["Interlocked"]
readerwriterlockslim["ReaderWriterLockSlim"]
cancellation_token["CancellationToken"]
cooperative_cancellation["協調キャンセル"]
wait_handle["待機ハンドルによる待機"]
thread_abort["Thread.Abort"]
polling_wait["ポーリングによる待機"]
control_invoke["Control.Invoke / InvokeAsync"]
ui_thread_context["UIスレッドのコンテキスト"]
wpf_dispatcher["Dispatcher(WPF)"]
shared_mutable_state -->|"原因になり得る"| race_condition
lock_ordering -->|"防止する"| deadlock
deadlock -->|"で確認できる"| monitor_tryenter
task_parallel_library -->|"の後継"| manual_thread_creation
task_parallel_library -->|"利用する"| managed_thread_pool
managed_thread_pool -->|"自動化する"| manual_thread_creation
asynchronous_io -->|"利用する"| managed_thread_pool
parallel_for -->|"実装を担う"| task_parallel_library
parallel_for -.->|"原因になり得る"| parallel_overhead
parallel_for -.->|"原因になり得る"| deadlock
thread_local_state -.->|"軽減する"| shared_mutable_state
channel_t -->|"防止する"| shared_mutable_state
channel_t -.->|"実装を担う"| backpressure
blockingcollection -->|"実装を担う"| backpressure
channel_t -.->|"の後継"| blockingcollection
concurrent_collection -->|"用いるのは非推奨"| backpressure
dedicated_lock_object -->|"軽減する"| deadlock
lock_statement -->|"両立しない"| plain_await
semaphoreslim -->|"実装を担う"| dedicated_lock_object
interlocked -->|"防止する"| race_condition
readerwriterlockslim -.->|"防止する"| race_condition
cancellation_token -->|"実装を担う"| cooperative_cancellation
cancellation_token -->|"利用する"| wait_handle
cooperative_cancellation -->|"の後継"| thread_abort
wait_handle -->|"の後継"| polling_wait
control_invoke -->|"推奨される対応"| ui_thread_context
control_invoke -.->|"原因になり得る"| deadlock
wpf_dispatcher -->|"推奨される対応"| ui_thread_context
概念間の関係(全28件)
図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。
- 共有可変状態は競合状態(race condition)の原因になることがあります。
- ロック取得順序の統一はデッドロック(deadlock)を防ぎます。
- デッドロック(deadlock)はMonitor.TryEnter(タイムアウト付き)で確認できます。
- TPL(Task Parallel Library)はスレッドの自作(new Thread)の後継に当たります。
- TPL(Task Parallel Library)はマネージドスレッドプールを利用します。
- マネージドスレッドプールはスレッドの自作(new Thread)を自動化します。
- 非同期I/Oはマネージドスレッドプールを利用します。
- Parallel.For / Parallel.ForEachはTPL(Task Parallel Library)の実装を担います。
- Parallel.For / Parallel.ForEachは並列化のオーバーヘッドの原因になることがあります。
- Parallel.For / Parallel.ForEachはデッドロック(deadlock)の原因になることがあります。
- スレッドローカル状態は共有可変状態を軽減します。
- Channel<T>は共有可変状態を防ぎます。
- Channel<T>はbackpressureの実装を担います。
- BlockingCollection<T>はbackpressureの実装を担います。
- Channel<T>はBlockingCollection<T>の後継に当たります。
- スレッドセーフなコレクション型をbackpressureに用いることは推奨されません。
- 専用ロックオブジェクトはデッドロック(deadlock)を軽減します。
- lockステートメントはplain awaitと両立しません。
- SemaphoreSlimは専用ロックオブジェクトの実装を担います。
- Interlockedは競合状態(race condition)を防ぎます。
- ReaderWriterLockSlimは競合状態(race condition)を防ぎます。
- CancellationTokenは協調キャンセルの実装を担います。
- CancellationTokenは待機ハンドルによる待機を利用します。
- 協調キャンセルはThread.Abortの後継に当たります。
- 待機ハンドルによる待機はポーリングによる待機の後継に当たります。
- Control.Invoke / InvokeAsyncはUIスレッドのコンテキストに対する本記事の推奨です。
- Control.Invoke / InvokeAsyncはデッドロック(deadlock)の原因になることがあります。
- Dispatcher(WPF)はUIスレッドのコンテキストに対する本記事の推奨です。
主要概念の定義
機械可読データ
このデータセットについて
このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。