『Javaの理論と実践: 並行コレクション・クラス』を読んで

並行コレクション・クラス

記事: Javaの理論と実践: 並行コレクション・クラス

メモ:

  • Doug Lea 氏の util.concurrent がいけてる
  • Map の歴史
    • Hashtable: JDK 1.0 登場。同期化された Map。同期化が必要ない場合に遅い。
    • HashMap と Collections.synchronizedMap: JDK1.2 で登場。同期化されない基底クラスと同期化されたラッパークラスで使い分けが可能に。
  • Hashtable と HashMap の問題点
    • 両者ともテーブルにアクセスできるスレッドは一つだけというスケーラビリティの問題
    • イテレーション・put-if-absent などの復号オペレーションには追加の同期が必要という問題
      • これは特に「条件付きスレッド・セーフ」と呼び、開発者に誤った認識を与える
    • Hashtable などは一個のロックで同期化するのでスケーラビリティがなくなる
  • ロックの粒度を低くすることで解決できる(ハッシュバケットごとのロックなど)
    • それでも size() や isEmpty() を使おうとすると、全部のロックが必要になる
  • ConcurrentHashMap の登場
    • java.util.concurrent のスレッドセーフな Map
    • 複数スレッド読み取り可能
      • 特に get はロックフリー的な実装で、高度な実装になっている(次回紹介予定)
    • 複数読み書きもほぼ同時に可能
    • 複数書き込みもほとんどの場合同時に可能
  • ポイント:呼び出し側との決めごとを緩めることでパフォーマンスをあげる
    • get は直近の値かもしれないし、同時進行中の設定中の値かもしれない
    • イテレータは追加・削除を反映するかもしれないし、反映しないかもしれない
  • CopyOnWriteArrayList
    • 変更時にだけロックする Array
    • 実装:不変配列の可変参照をもっている。 変更時に参照を付け替える。
    • イテレータは不変配列を参照するのでおかしくはならない。
    • 読み取りが多い場合向け
  • 結論
    • 完全な同期化を提供する Hastable、Vector の完全な代替にはならない。
    • ただし、たいていの場合 CopyOnWriteArrayList と ConcurrentHashMap で問題ない。