SHELL模擬多線程腳本的詳細註解

在網上看到shell模擬多線程的腳本,看了一下,估計對於新手還是很難理解,本文將進行更加詳細的註解。

其實這個腳本並沒有實現多線程,shell也根本不可能實現多線程。
此腳本的作用無非是限制幾乎同時放入後臺執行的進程數量而已,從而達到在提高腳本執行效率的同時又不明顯增加負載的作用。

原始腳本如下:

#!/bin/bash

SEND_THREAD_NUM=13
tmp_fifofile="/tmp/$$.fifo"
mkfifo "$tmp_fifofile"
exec 6<>"$tmp_fifofile"

for ((i=0;i<$SEND_THREAD_NUM;i++));do
                 echo                                                                                    
done >&6

for i in `seq 1 100`;do                                                        
                 read -u6                                                                        

                 {
                                 echo $i                                                
                                 sleep 3                                                
                                 echo >&6                                        
                 } &

                pid=$!
                echo $pid
done

wait

exec 6>&-

exit 0

以下爲詳細註解。

#設置線程數,在這裏所謂的線程,其實就是幾乎同時放入後臺(使用&)執行的進程。
SEND_THREAD_NUM=13
# 腳本運行的當前進程ID號作爲文件名,其實這樣命名只是爲了防止創建管道文件時與現有文件名重複,從而引起創建失敗,別無他用。
tmp_fifofile="/tmp/$$.fifo"                  
#創建管道文件
mkfifo "$tmp_fifofile"
#把文件描述符6指向管道文件,文件描述符可以使用3-9任意一個即可(除了5),0、1、2、5已有定義,具體可參考關於文件描述符的文章。
EXEC 6<>"$tmp_fifofile"            
#刪除管道文件,其實刪不刪無所謂,看你自己了。
rm -f $tmp_fifofile

#使用一個for循環向管道中輸入$SEND_THREAD_NUM個空行;>符號爲輸出重導向;&符號表示6爲文件描述符,也就是說&6表示文件描述符6.
for ((i=0;i<$SEND_THREAD_NUM;i++));do
         echo                                        
done >&6

for i in `seq 1 100`;do                            # 100 次 for 循環開始,也就是說表示100次你的實際應用
         read -u6                                    # 從文件描述符6(即管道)中讀取行,每次讀一行,由於是管道,讀一行,管道中便少一行,每次只能讀取一行,注意:如果讀完了,便會掛起,直到管道中再次有可讀的行。

         {
                 echo $i                         # 打印i,這裏代表整個腳本的應用部分,可以替換成你的實際應用。
                sleep 3                         # 暫停3秒,這裏是關鍵點,其實引入管道模擬多線程的關鍵就是爲了這個暫停的3秒(實際上是微大於3秒的),讓系統有個緩衝的時間,起到限制所謂併發的進程數量。
                 echo >&6                    # 再次往管道文件中寫入一個空行,爲了掛起的for循環能夠繼續執行。
         } &    #注意這裏要放到後臺,也就是說echo $i這個你的應用有13個是幾乎同時在後臺執行的,爲什麼是13個呢?當for循環完13次後會掛起,因爲管道已經空了,read -u6會暫時掛起,直到管道中有了空行。由於本commands block(即{}中的內容)是放在後臺執行的,可以理想的看成這13次循環是同時執行的,大家同時sleep了3秒,而又同時向管道中輸入了空行,所以管道在讀空之後差不多3秒的時候又瞬時多了13次空行,使得read -u6能夠繼續讀行,for循環得以繼續執行。

        pid=$!                                 #  $!代表在後臺執行的最後一個進程。
        echo $pid                            #打印最後一個進入後臺的子進程id;打印的pid結果印證了非併發,非多線程。

done

wait   #等到後臺的進程都執行完畢。

exec 6>&-                                    #刪除文件描述符6

exit 0


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章