第十章: 生存事故

1時半就寝・7時半起床。

ロック順によるデッドロック

最も良くある生存事故のパターン。全てのスレッドが同じ順序でロックを取得しないと、デッドロックに陥る可能性がある。

public void leftRight() {
  synchronized(left) {
    synchronized(right) {
      ...
    }
  }
}
public void rightLeft() {
  synchronized(right) {
    synhronized(left) {
      ...
    }
  }
}

複数のロックを用いなければこのような問題は発生しないが、複数ロックを使用する場合はグローバルにロック順序が固定化されていないといけない。実装の中身のみならず、呼び出し側が引数を入れ替えたりする可能性もあるので注意。

協力によるデッドロック

ロックを保持した状態で他のオブジェクトのメソッドを呼び出すと、他のオブジェクトのメソッドが別のロックを入手してデッドロックに陥る可能性がある。
相互に関連するオブジェクト同士がsynchronizedメソッドを呼び出し合うとこのような事態を引き起こし易い。
対応方法としては、出来る限りオープンコール(synchronizedではないメソッド)として実装を行うこと。メソッド全体をsynchronizedにしないといけないことは殆ど無い。出来るだけsynchronizedブロックを小さくし、共有ステートに関係する操作だけをロックでガードすべき。