web-dev-qa-db-ja.com

共有および排他的ロック

共有または排他的に保持できる「ロック」が必要です。これにより、次の一連のイベントに対して次の動作が提供されます。

  1. プロセスA:要求し、共有ロックが付与されます
  2. プロセスB:排他ロックを要求し、Aのロックの所有権によってブロックされます
  3. プロセスC:共有ロックを要求し、Bが排他ロックの列にあるためにブロックされます

Unix flockがこれらのセマンティクスを提供すると思っていましたが、ステップ3で、プロセスCの共有ロックの要求がsucceedであり、プロセスBの排他ロックの要求であることがわかりました。共有ロックが保持されていない場合にのみ付与されます。これには、(私にとって)不幸な効果があり、共有ロックを要求する同時プロセスが多いほど、排他ロックを要求するプロセスは、未処理の共有ロックが保持されていないウィンドウを待機する時間が長くなります。

言い換えれば、私が求めている動作は、プロセスがrequests排他的ロックを実行してから、ロックが付与されるまで、そしてロックを解放するまで、すべて後続の共有ロック要求はキューに入れられ、ブロックされます。

どのタイプのロックに必要なプロパティがありますか?

2
Chap

書き込みロックを優先する 読み取り/書き込みロック が必要です。 A posixのrwlockを設定して、初期化中にライターを優先することができます。

または、リンクされたwikiページで述べたように:

書き込み優先のRWロックは、新しいリーダーがロックを取得できないようにすることにより、ライターの枯渇の問題を回避しますキューに入れられてロックを待機しているライターがある場合。ライターは、すでにロックを保持しているすべてのリーダーが完了するとすぐにロックを取得します。欠点は、書き込み優先のロックでは、読み取り優先のRWロックと比較して、ライタースレッドが存在する場合の同時実行性が低くなることです。また、読み取りまたは書き込みのいずれかでロックを取得または解放する各操作はより複雑であり、内部的に1つではなく2つのミューテックスを取得および解放する必要があるため、ロックのパフォーマンスは低下します。このバリエーションは、「書き込みバイアス」リーダーライターロックとも呼ばれます。

2
ratchet freak

任意のロック構造を構築するために本当に必要なのは、ミューテックスと状態変数だけです。ファイルシステムのコンテキストでは、ミューテックスは、取得するopen("/tmp/foo.lock", O_WRONLY|O_TRUNC|O_CREAT|O_EXCL)(その後にclose()を呼び出す)と解放するremove("/tmp/foo.lock")で構成されます。ミューテックスをブロックするには、 inotify を使用するか、(ロックされたままにならないか、ロックの競合が激しくなることがわかっている場合は)ビジーウェイトを使用します。状態変数は、/tmp内のセカンダリファイルにすることができます(または、プログラムがクラッシュした後、古いファイルを手動でクリーンアップできる場合は他の場所にあります)。残りの部分は、設計がかなり簡単なはずです。

0
Kevin