並行して実行されるbashスクリプトでロックファイル機能を使用したいと思います。問題は、以下のスクリプトの関数から最初のロックされた関数をすぐに再呼び出しすると、飢餓現象が発生する可能性があることです。lockfile
ポーリングタイムアウトが異なるプロセスがロックを取得できるほど十分に大きいようです。
本当に?では、どうすれば対処すべきでしょうか?
lockfile test.lock
echo "TESTING $$"
sleep 10
rm test.lock
たとえば、
2つのシェル:
SH1とSH2が一緒にスクリプトを実行し、
SH1がロックを獲得し、SH2がブロックされます。
問題:
SH1がロックを完了して削除しても、SH2はまだブロックされ(約1秒間...)、SH1がスクリプトを繰り返すと、SH2は永久にブロックされます。
ベストアンサー1
ロックファイルを刺してもスリープ状態にならないため、ロックファイルをtmpfsに入れる必要があります。
これには2つの解決策があります。
一部のプロセスでは静的睡眠で十分です。
WAIT=5 # max seconds between two procs; larger is nicer for the system
lockfile -${WAIT} -r-1 "${LOCKFILE}"
## payload
rm -f "${LOCKFILE}"
# sleep outside the lock for at least $WAIT seconds
# to give another proc a chance to lock it
sleep ${WAIT}s
ランダムな睡眠は多くのプロセスを処理しますが、非常に良いではありません。
MAX=5
MIN=3
WAIT=$((MIN+RANDOM/(1+MAX-MIN))) # random sleep between min and max
lockfile -${WAIT} -r-1 "${LOCKFILE}"
## payload
rm -f "${LOCKFILE}"
# sleep outside the lock for at least $WAIT seconds
# to give another proc a chance to lock it
sleep ${WAIT}s
ウェイターは、持続時間が長くなるほど多くのプロセスに適しています。
MAX=600
MIN=1
WAIT=${MAX} # max seconds between two procs; larger is nicer
while ! lockfile -r0 "${LOCKFILE}"
do
sleep ${WAIT}s
WAIT=$(( WAIT / 2 )) # backoff formula
if [ ${WAIT} -lt ${MIN} ]; then
WAIT=${MIN}
fi
done
## payload
rm -f "${LOCKFILE}"
# reduced WAIT means likely to run again; alternatively use MAX
sleep ${WAIT}s