天天看點

shell多線程之程序間通信(2)

工作中往往遇到這種情況,有許多任務,依次執行比較浪費時間,由于任務之間有依賴關系,簡單的并發執行又不行。

就如同下面這種情況,任務new和dvidUser是可以并發執行的,fact任務依賴于new任務,fact執行完之後last和stat才能執行;

dvidUser執行完之後dvid和User兩個任務才能執行。

shell多線程之程式間通信(2)

針對這種情況,我考慮了作業系統中的信号量機制,通過借助linux中的檔案描述符(以下稱pipe)來實作這幾個任務的并發。

當new執行完之後,向pipe-7中寫入自己目前執行的ID(在程式中用$i辨別,遞增的),然後ID自增,繼續執行;

與此同時,fact任務不斷從pipe-7中讀取,我們稱之為$j,然後和自己的任務ID進行比較,會有幾種情況:

1.沒有讀到$j,說明相同ID的前置new任務尚未執行,則fact阻塞;

2.讀到$j,$j>ID,fact執行,fact執行完之後将自己的ID同時寫入pipe-8和pipe-9),以通知它的後置任務last和stat.

其他的邏輯基本相同。代碼如下:

init_pipe.sh

# 初始化file descriptor
init_pipe(){
[ -e /tmp/fd1001 ] || mkfifo /tmp/fd1001
exec 1001<>/tmp/fd1001
rm -rf /tmp/fd1001

[ -e /tmp/fd1002 ] || mkfifo /tmp/fd1002
exec 1002<>/tmp/fd1002
rm -rf /tmp/fd1002

[ -e /tmp/fd1003 ] || mkfifo /tmp/fd1003
exec 1003<>/tmp/fd1003
rm -rf /tmp/fd1003

[ -e /tmp/fd1004 ] || mkfifo /tmp/fd1004
exec 1004<>/tmp/fd1004
rm -rf /tmp/fd1004

[ -e /tmp/fd1005 ] || mkfifo /tmp/fd1005
exec 1005<>/tmp/fd1005
rm -rf /tmp/fd1005

[ -e /tmp/fd1006 ] || mkfifo /tmp/fd1006
exec 1006<>/tmp/fd1006
rm -rf /tmp/fd1006

}

destroy_pipe(){
exec 1001<&-
exec 1001>&-
exec 1002<&-
exec 1002>&-
exec 1003<&-
exec 1003>&-
exec 1004<&-
exec 1004>&-
exec 1005>&-
exec 1005<&-
exec 1006<&-
exec 1006>&-
}      

work.sh

# 初始化file descriptor
#source init_pipe.sh source執行腳本,兩個腳本在同一個程序中,執行腳本中的環境變量都可以帶到主腳本。
# ‘.’=fork,開啟一個新的子shell,子shell執行完之後傳回父shell,不能帶回自己的環境變量;
. init_pipe.sh
newFun(){
for((i=0;i<10;i++))
do
    echo 'new'$i
    sleep 1
    echo $i >& 1001
done
}

factFun(){
for((i=0;i<10;i++))
do
    read -u 1001 j
    if [ $i -le $j ];then
            echo 'fact'$i
            echo $i>& 1002
            echo $i>& 1003
            echo $i>& 1004
    fi
    sleep 1
done
}

lastFun(){
for((i=0;i<10;i++))
do
    read -u 1002 j
    if [ $i -le $j ];then
            echo 'last'$i
    fi
    sleep 1
done
}

statFun(){
for((i=0;i<10;i++))
do
    read -u 1003 j
    if [ $i -le $j ];then
            echo 'stat'$i
    fi
    sleep 1
done
}
retainFun(){
for((i=0;i<10;i++))
do
    read -u 1004 j
    if [ $i -le $j ];then
        echo 'retain'$i
    fi
    sleep 1
done
}

dvidUserIdFun(){
for((i=0;i<10;i++))
do
        echo 'dvidUserId'$i
        echo $i>& 1005
        echo $i>& 1006
    sleep 1
done
}

dvidFun(){
for((i=0;i<10;i++))
do
    read -u 1005 j
    if [ $i -le $j ];then
            echo 'dvid'$i
    fi
    sleep 1
done
}

userIdFun(){
for((i=0;i<10;i++))
do
    read -u 1006 j
    if [ $i -le $j ];then
            echo 'userId'$i
    fi
    sleep 1
done
}
###################################################
init_pipe
start_time=`date +%s`
newFun &
factFun &
lastFun &
statFun &
retainFun &
dvidUserIdFun &
dvidFun &
userIdFun &
wait
end_time=`date +%s`
echo "TIME:[[ $end_time - $start_time]]"

destroy_pipe      

轉載于:https://www.cnblogs.com/wangbin2188/p/9897694.html

繼續閱讀