天天看點

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;釋放信号量則相反。