天天看点

bash实现互斥、信号量的方法

【通过fifo实现信号量】

利用fifo的block-reading实现。

#!/bin/bash

conf_max_currency=10

conf_sem_file=/tmp/$.fifo

conf_fifo_fd=123 # 123 for example, or any expect 0,1,2

# init

mkinfo ${conf_sem_file}

exec ${conf_fifo_fd}<>${conf_sem_file}

rm ${conf_sem_file}

for (( i = 0; i < ${conf_max_currency}; i++ ))

do

echo

done >&${conf_fifo_fd}

for ((i = 0; i < 1000; ++i))

do

read -u ${conf_fifo_fd} # block if nothing in fifo

{

# do your job here

echo # write to fifo means free sem

} >&${conf_fifo_fd}

done 

【通过flock+文件实现互斥和信号量】

假设worker.sh为处理脚本(下同)

1、在调度worker.sh时(也就是worker.sh的外层)互斥,可以简单的通过flock实现。

优点:

将worker的逻辑与锁过程解耦

缺点:

需要统一的入口调度worker.sh

flock /path/to/lock-file work.sh 

2、在worker.sh内实现互斥

文件lockfile.lock记录当前的锁curlock(唯一表示一个锁的特性值,如pid),通过flock实现lockfile.lock的互斥修改。

加锁过程:

1)flock读取当前锁curlock,curlock为空,记录特性锁到所文件lockfile.lock,否则重复读取当前锁curlock并验证的过程。

2)锁获取后即返回状态;锁超时或失败则可以相应的定义返回。

解锁过程:

与加锁过程类似,只是进行相反的过程。

简单的实例如下:

#!/bin/bash

config_lock_file="/tmp/xx_lock_file.lock"

config_free_lock="FREE"

if [ ! -f ${config_lock_file} ];then

echo ${config_free_lock} > ${config_lock_file}

fi

function mutex_lock()

{

local lock_name=$1

if [ "x${lock_name}" = "x" ];then

lock_name=$

fi

flock ${config_lock_file} echo > /dev/null && while curlock=`cat ${config_lock_file}`; do if [ "${curlock}" = "${config_free_lock}" -o "${curlock}" = "$

{lock_name}" ];then echo ${lock_name} > ${config_lock_file}; break; fi ; done

echo "${lock_name}"

return 0

}

function mutex_unlock()

{

local lock_name=$1

if [ "x${lock_name}" = "x" ];then

lock_name=$

fi

flock ${config_lock_file} echo > /dev/null && curlock=`cat ${config_lock_file}` && if [ "${curlock}" = "${lock_name}" ];then echo ${config_free_lock} > $

{config_lock_file}; fi

return 0

上面的例子很简单,需要处理的问题还有很多:

1)例子中锁是持久的、强制的,lock、unlock出现不匹配的情况下,就是杯具,因此要考虑到lock之后没有unlock的情况。比如,通过限制锁的最长有效期(可以简单的通过lockfile.lock的mtime判断),过期的锁等价于FREE

2)性能消耗

3)try_lock实现

3、实现信号量

基于上面的例子,实现信号两就比较简单了,之间将写入所文件的内容置为当前的信号数量,每获取一个信号就将文件中的数字减小1;释放信号量则相反。