はじめに
Javaでマルチスレッドプログラミングをしていると、「スレッドセーフなMapが欲しい」という場面が必ず出てきます。
そんなときに登場するのが…
👉 ConcurrentHashMap
でも、
- 「どうしてこれがスレッドセーフなの?」
- 「HashMapとは何が違うの?」
- 「全部ロックしてるの?」
そんな疑問を、わかりやすく図解&実例付きで解決します!
HashMapとの違い:まずはここを理解!
通常の HashMap
はスレッドセーフではありません。
複数スレッドが同時に書き込むと…
- 内部構造が壊れる
- 無限ループになる
- 例外が出ることも
それに対して ConcurrentHashMap
は、高速性と安全性を両立した設計になっています!
どうやってスレッドセーフを実現しているの?
Java 8 以降の ConcurrentHashMap
は、以下の工夫でスレッドセーフを実現しています。
技術要素 | 説明 |
---|---|
CAS(Compare-And-Swap) | ロックなしでバケットへの最初の挿入を高速化 |
局所ロック | 必要なノードだけロックするから他に影響なし |
ロックストライピング | 小さなロックを複数に分けて同時処理可能に |
TreeBin(赤黒木) | ノードが多い場合に木に変えて高速検索 |
再ハッシュの工夫 | 分散処理で拡張時も安全・効率的 |
volatileと可視性制御 | 最新状態の読み取りを保証し構造一貫性を守る |
実際の処理の流れ(図解)
① put(key, value) の流れ
key.hashCode()
を元にインデックス計算- バケットが空 → CASでノード挿入(ロックなし)
- 既にノードがある → 局所ロックで更新
- ノード数が閾値超えたら → TreeBinに変換
- 要素数が増えたら → 拡張(resize)を並列実行
② get(key) の流れ
1 2 |
Integer value = map.get("apple"); |
- 読み取りは基本的にロックなし!
volatile
やJavaメモリモデルによって「構造の一貫性」が保証されている
実用例:マルチスレッド環境での使用
1 2 3 4 5 6 7 |
ConcurrentHashMap<String, Integer> stock = new ConcurrentHashMap<>(); stock.put("apple", 50); // 別スレッドから安全に更新 stock.compute("apple", (k, v) -> v == null ? 1 : v + 1); |
このように、複数スレッドが同時に読み書きしても安全!
なぜ synchronizedMap より速いの?
Collections.synchronizedMap(...)
はすべての操作で全体をロックするConcurrentHashMap
は操作対象だけにロック or ロック不要
→ 並列性能が大幅に向上!
nullキー・null値には注意!
1 2 |
map.put(null, 100); // ❌ NullPointerException! |
ConcurrentHashMap
は キーにも値にも null を許しません- 理由:スレッド間の判別が難しくなり、安全性が損なわれるため
Java 7以前との違いは?
バージョン | ロックの仕組み | 特徴 |
---|---|---|
Java 7以前 | Segmentロック | 区切ったエリアごとにロック |
Java 8以降 | ノード単位+CAS | より細かく・高速に |
パフォーマンスの工夫:TreeBinとresize
- ノード数が多いと遅くなる → **リスト → 木(赤黒木)**に変換!
- 拡張時も全体で一気にやらず、スレッドごとに手分けして拡張
よくある勘違いQ&A
Q. 完全にロックフリー?
A. いいえ。書き込み操作は一部ロックを使います。
Q. Mapの内容をループで読むときは?
A. ConcurrentModificationExceptionは起きません!
ただし、読み取り中に内容が変わる可能性はあります。
まとめ:ConcurrentHashMapのスゴさ
- 読み込みはロックなしで高速
- 書き込みは必要最小限のロックで安全
- ノードが多くなっても木化して検索速度を保つ
null
禁止で予期しないバグを回避- マルチスレッドでのパフォーマンスが非常に高い
自己学習・実務対策に!
「ConcurrentHashMap」レベルの知識は中級者以上のJava開発で必須!
- 自分で学びたい人は → 絶対にJavaプログラマーになりたい人へ。
- 現場レベルの設計やレビューを受けたい人は → サイゼントアカデミー
コメント