ロックの管理

マルチスレッドのコードがデッドロックを含まないことを保証するために、Julia では次の戦略が使われています。これは基本的にコフマンの第四条件 (環状 wait) を避けるためのものです:

  1. ロックを一度に一つずつ取得するようにコードを構成する。
  2. 共有ロックは必ず同じ順番 (後述) で取得する。
  3. 制限のない再帰を必要とする構文を避ける。

ロック

Julia システムに存在するロックと発生する可能性のあるデッドロックを割けるための使用方法を次に示します1 (ダチョウのアルゴリズムは許されません)。

次に示すのは一番下のリーフロック (レベル 1 のロック) です。これらのロックを保持しているときに他の任意のロックを取得してはいけません:

次に示すのはレベル 2 のリーフロックであり、内部でレベル 1 のロック (safepoint_lock) だけを取得できます:

次に示すのはレベル 3 のロックであり、内部でレベル 1 またはレベル 2 のロックだけを取得できます:

次に示すのはレベル 4 のロックであり、内部でレベル 1・レベル 2・レベル 3 のロックだけを取得できます:

ここまでのロックを保持した状態で Julia コードを実行することは許されません。

次に示すのはレベル 6 のロックであり、内部ではレベルが 5 以下のロックだけを取得できます:

次に示すのはほぼルートのロック (レベル end - 1 のロック) です。つまり、このロックの取得を試みるときに保持していてよいのはルートロックだけです:

次のロックは IO 操作の同期に使われます。ここまでのロックを保持したまま任意の IO (例えば警告メッセージやデバッグ情報の出力) を行うと、見つけにくい致命的なデッドロックが引き起こされる可能性があります。気を付けて!

次に示すのがルートロックです。つまり、このロックの取得を試みるときに他のロックを保持していてはいけません:

壊れたロック

次のロックは壊れています:

共有されるグローバルなデータ構造

次のデータ構造はグローバルに共有される可変な状態なので、それぞれ対応するロックが必要です。これは上記のロックの優先順序リストを反対にしたものです。レベル 1 のリーフリソースは簡単なのでここには示されていません。


  1. 訳注: ロックの名前をソースコードと合うように変更し、現在のバージョンに存在しないロック pagealloc_lock は削除した (参照: コミット 81bde)。[return]

広告