知識マップ: マルチスレッドの実務ベストプラクティス Java編 ── 仮想スレッド時代の定石
記事「マルチスレッドの実務ベストプラクティス Java編 ── 仮想スレッド時代の定石」の主張を、概念と関係(エッジ)に分解した知識グラフの全体です。各関係には根拠・確認日・確度が付いています。
Javaでは共有データの見え方がメモリモデルのhappens-before関係で定義されており、同期なしの共有変数は未定義動作にはならないものの、古い値が見え続けたり書き込みの順序が入れ替わって見えたりするメモリ一貫性エラーが正当に起こります。実務指針は、素の共有変数で工夫せずjava.util.concurrentの道具にhappens-beforeを作らせることです。スレッドはExecutorServiceに任せ、I/O待ちが主体のタスクはJDK 21で正式化された仮想スレッドへ、CPUバウンドはコア数程度のプラットフォームスレッドへ振り分けます。仮想スレッドはプールせず、同時実行数の制限はSemaphoreで表現します。JDK 21〜23のsynchronizedによるピン留めはJDK 24のJEP 491で解消されました。停止は割り込みによる協調停止が唯一の正解で、Thread.stopは現在UnsupportedOperationExceptionになります。
flowchart LR
accTitle: Javaのマルチスレッド設計ベストプラクティスの知識マップ
accDescr: Javaメモリモデルのhappens-beforeとメモリ一貫性エラー、ExecutorServiceと仮想スレッドの使い分け、JDK 24で解消されたピン留め、並行コレクションとBlockingQueueによる共有の削減、割り込みによる協調停止と2段階シャットダウン、SwingのEDTを示す図
shared_mutable_state["共有可変状態"]
java_memory_model["Javaメモリモデルとhappens-before"]
race_condition["競合状態(race condition)"]
memory_consistency_error["メモリ一貫性エラー"]
happens_before["happens-before関係"]
volatile_keyword["volatile"]
java_atomic_classes["Atomic系クラス(AtomicInteger / LongAdder)"]
executor_service["ExecutorService"]
manual_thread_creation["スレッドの自作(new Thread)"]
backpressure["backpressure"]
virtual_thread["仮想スレッド"]
io_bound_task["I/Oバウンドなタスク"]
cpu_bound_task["CPUバウンドなタスク"]
java_semaphore["Semaphoreによる同時実行数制限"]
concurrency_limiting["同時実行数の制限"]
carrier_thread_pinning["キャリアスレッドへのピン留め"]
synchronized_block["synchronizedブロック"]
dedicated_lock_object["専用ロックオブジェクト"]
reentrant_lock["ReentrantLock"]
lock_ordering["ロック取得順序の統一"]
deadlock["デッドロック(deadlock)"]
thread_local_state["スレッドローカル状態"]
concurrenthashmap_computeifabsent["ConcurrentHashMap.computeIfAbsent"]
blockingqueue["BlockingQueue"]
thread_interruption["割り込み(interruption)"]
cooperative_cancellation["協調キャンセル"]
thread_stop_suspend["Thread.stop / suspend / resume"]
executor_two_phase_shutdown["ExecutorServiceの2段階シャットダウン"]
deadline_bounded_shutdown["期限内の停止処理"]
swing_edt["イベントディスパッチスレッド(EDT)"]
ui_thread_context["UIスレッドのコンテキスト"]
jstack_thread_dump["スレッドダンプ(jstack / jcmd)"]
structured_concurrency["構造化並行性(StructuredTaskScope)"]
scoped_values["Scoped Values"]
shared_mutable_state -->|"原因になり得る"| race_condition
shared_mutable_state -->|"原因になり得る"| memory_consistency_error
java_memory_model -->|"利用する"| happens_before
happens_before -->|"防止する"| memory_consistency_error
volatile_keyword -->|"用いるのは非推奨"| race_condition
java_atomic_classes -->|"防止する"| race_condition
executor_service -->|"の後継"| manual_thread_creation
executor_service -.->|"前提とする"| backpressure
virtual_thread -.->|"推奨される対応"| io_bound_task
virtual_thread -->|"用いるのは非推奨"| cpu_bound_task
java_semaphore -->|"推奨される対応"| concurrency_limiting
virtual_thread -.->|"原因になり得る"| carrier_thread_pinning
synchronized_block -.->|"両立しない"| carrier_thread_pinning
synchronized_block -->|"前提とする"| dedicated_lock_object
reentrant_lock -.->|"の後継"| synchronized_block
lock_ordering -->|"防止する"| deadlock
thread_local_state -.->|"軽減する"| shared_mutable_state
concurrenthashmap_computeifabsent -->|"防止する"| race_condition
blockingqueue -->|"実装を担う"| backpressure
thread_interruption -->|"実装を担う"| cooperative_cancellation
thread_interruption -->|"の後継"| thread_stop_suspend
executor_two_phase_shutdown -->|"利用する"| thread_interruption
executor_two_phase_shutdown -->|"推奨される対応"| deadline_bounded_shutdown
swing_edt -->|"実装を担う"| ui_thread_context
deadlock -->|"で確認できる"| jstack_thread_dump
jstack_thread_dump -->|"用いるのは非推奨"| virtual_thread
structured_concurrency -.->|"利用する"| virtual_thread
scoped_values -->|"の後継"| thread_local_state
概念間の関係(全28件)
図と同じ関係を文章でも列挙します。表示している文と機械可読な意味データ(RDFa)は同じ要素に載っています。確度が「確立した関係」のものは直接の関係として、「条件付きの関係」のものは成立条件つきの言明(rdf:Statement)として表現しています。
- 共有可変状態は競合状態(race condition)の原因になることがあります。
- 共有可変状態はメモリ一貫性エラーの原因になることがあります。
- Javaメモリモデルとhappens-beforeはhappens-before関係を利用します。
- happens-before関係はメモリ一貫性エラーを防ぎます。
- volatileを競合状態(race condition)に用いることは推奨されません。
- Atomic系クラス(AtomicInteger / LongAdder)は競合状態(race condition)を防ぎます。
- ExecutorServiceはスレッドの自作(new Thread)の後継に当たります。
- ExecutorServiceはbackpressureを前提とします。
- 仮想スレッドはI/Oバウンドなタスクに対する本記事の推奨です。
- 仮想スレッドをCPUバウンドなタスクに用いることは推奨されません。
- Semaphoreによる同時実行数制限は同時実行数の制限に対する本記事の推奨です。
- 仮想スレッドはキャリアスレッドへのピン留めの原因になることがあります。
- synchronizedブロックはキャリアスレッドへのピン留めと両立しません。
- synchronizedブロックは専用ロックオブジェクトを前提とします。
- ReentrantLockはsynchronizedブロックの後継に当たります。
- ロック取得順序の統一はデッドロック(deadlock)を防ぎます。
- スレッドローカル状態は共有可変状態を軽減します。
- ConcurrentHashMap.computeIfAbsentは競合状態(race condition)を防ぎます。
- BlockingQueueはbackpressureの実装を担います。
- 割り込み(interruption)は協調キャンセルの実装を担います。
- 割り込み(interruption)はThread.stop / suspend / resumeの後継に当たります。
- ExecutorServiceの2段階シャットダウンは割り込み(interruption)を利用します。
- ExecutorServiceの2段階シャットダウンは期限内の停止処理に対する本記事の推奨です。
- イベントディスパッチスレッド(EDT)はUIスレッドのコンテキストの実装を担います。
- デッドロック(deadlock)はスレッドダンプ(jstack / jcmd)で確認できます。
- スレッドダンプ(jstack / jcmd)を仮想スレッドに用いることは推奨されません。
- 構造化並行性(StructuredTaskScope)は仮想スレッドを利用します。
- Scoped Valuesはスレッドローカル状態の後継に当たります。
主要概念の定義
機械可読データ
このデータセットについて
このページはサイトの知識グラフ(_data/knowledge/)から自動生成されています。誤りの指摘はお問い合わせからお願いします。