『Javaの理論と実践: JDK 5.0における、より柔軟でスケーラブルなロック』を読んで

記事:Javaの理論と実践: JDK 5.0における、より柔軟でスケーラブルなロック

メモ:

  • synchronized の特性
    • 原子性(atomicity)と可視性(visibility)を提供
    • 原子性:モニタオブジェクトに保護されたコードを実行できるのは一度に一つだけ
    • 可視性:同じモニタオブジェクトで保護されたメモリは synchronized ブロックに入る前に必ずみえる
      • volatile でも提供される
  • 同期化の改善
    • synchronized でブロックしている間にスレッドに割り込めない
    • synchronized によるロック・アンロックは同じスタックフレームで行われる必要がある
  • java.util.concurrent.lock
    • ロックを抽象化
    • 言語機能ではなく、クラスとして実装
    • 異なったスケジューリングアルゴリズム、パフォーマンス特性、意味体系を持つ実装に変更可能
  • ReentrantLock
    • セマンティクスは(再突入可能性など)は synchronized と同じ
    • ロックポーリング、タイムロックウェイト、割り込み可能ロックなどの機能が追加
    • ただし、unlcok() メソッドを呼ばないとデッドロックする
    • JDK 1.5 時点では synchronized よりスケーラブル
    • ReentrantLock と synchronizedのスケーラビリティ
      • 疑似乱数生成の簡単なベンチマークでは ReentrantLock でスケーラビリティが高いことが示された
  • 条件変数(ConditionalVariable)
    • Object クラスにはスレッド通信のための wait(), notify(), notifyAll() がある
    • これらは高度でセンシティブな機能なので使わない方がいい。
      • 例:wait(), notify() などをするには当該オブジェクトへのロックが必要
  • Condition
    • wait(), notify(), notifyAll() の代わりになる。
    • await(), signal() signalAll() という名前になっている
      • wait() などはオーバーライドできないため代用の名前を使っている
  • フェアなロックとアンフェアなロック
    • ロック取得とロック解放の順序が保証されるかどうか。
    • フェア性を保証するとコストが高い
    • 必要でない限りはアンフェアがおすすめ
    • synchronized はフェアではない
  • ReentrantLock が最強ではない
    • ReentrantLock は高度な機能を持っている。普通は synchronized でよい。
    • synchronized ではロックの解放忘れがありえない
    • synchronized で保持しているロック情報はスレッドダンプに出せる
    • synchronized なら多くの開発者が理解可能