我想对并行运行的 bash 脚本使用锁定文件功能。问题是,在下面脚本中的功能中,如果立即再次调用第一个锁定的函数,则可能会发生饥饿。看起来lockfile
轮询的超时时间足够大,以允许其他进程获取锁。
真的吗?那应该如何处理呢?
lockfile test.lock
echo "TESTING $$"
sleep 10
rm test.lock
例如:
两个 shell :
SH1、SH2 一起运行脚本,
SH1 获取锁,SH2 被阻止。
问题:
当 SH1 完成并移除锁时,SH2 仍然被阻止(大约一秒钟......),如果 SH1 循环运行脚本,SH2 将被永久阻止。
答案1
您应该将锁文件放在 tmpfs 上,因为戳锁文件会阻止它休眠。
这里有两个解决方案:
静态睡眠;对于一些进程来说足够了
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
答案2
我不确定是否有问题。
这fs/locks.c 的内核代码包含以下评论:
519 /* Insert waiter into blocker's block list.
520 * We use a circular list so that processes can be easily woken up in
521 * the order they blocked. The documentation doesn't require this but
522 * it seems like the reasonable thing to do.
523 */
如果您仍然不相信这一点,唯一合理的选择是使用信号量,semop(2)、semget(2)。