【shell二三軼事】多線程如何實(shí)現(xiàn)?原子操作如何實(shí)現(xiàn)?

【前言】

shell中并沒(méi)有真正的多線程,我們這里講的多線程,實(shí)際上是多進(jìn)程,即最大化地使用cpu。

【正文】

1. 初級(jí)版

在linux或shell中,&一般放在某條命令的末尾,可以把該條命令放到一個(gè)后臺(tái)進(jìn)程去處理。
比如:

ls &

這個(gè)時(shí)候,我們應(yīng)該可以想到一種多線程的實(shí)現(xiàn)方式。
那就是,循環(huán)。

for item in xxx
do
    耗時(shí)操作 &
done
wait

這里,wait的作用就是等到所有的后臺(tái)進(jìn)程執(zhí)行完畢,才會(huì)執(zhí)行后面的命令。
這時(shí)候,出現(xiàn)一個(gè)新的問(wèn)題。
我們每循環(huán)一次就會(huì)打開一個(gè)后臺(tái)進(jìn)程,循環(huán)次數(shù)少的時(shí)候尚可,循環(huán)次數(shù)多了怎么辦?
后臺(tái)進(jìn)程開的太多,我們的系統(tǒng)難免會(huì)崩潰,那么我們?nèi)绾蜗拗坪笈_(tái)進(jìn)程開啟的數(shù)量呢?

2. 進(jìn)階版

對(duì)于上面的問(wèn)題,我們很容易想到一種解決方法。
那就是,兩層循環(huán)。

threads=20
for item in xxx
do
    for((i=0;i<$threads;i++))
    do
        耗時(shí)操作 &
    done
    wait
done

這個(gè)方法,其實(shí)也是有點(diǎn)問(wèn)題的。
如果,我們同時(shí)開了20個(gè)后臺(tái)進(jìn)程,其中有一個(gè)跑的特別慢,那么即使其他19個(gè)進(jìn)程的任務(wù)都跑完了,程序還是會(huì)繼續(xù)等待。這樣下來(lái),我們的速度其實(shí)并沒(méi)有多快,這種多線程是有殘缺的多線程,并不完美。

3. 高級(jí)版(主流)

其實(shí)當(dāng)前的主流就是使用命名管道(fifo)的方式,去實(shí)現(xiàn)進(jìn)程數(shù)量的可控。

threads=50
mkfifo testfifo  #新建一個(gè)fifo類型的文件
exec 100<>testfifo  #以讀寫方式打開文件,并把文件描述符fd100指向該文件 
rm -rf testfifo #該文件可以刪掉(原因是存在未關(guān)閉的fd,所以實(shí)際上文件并沒(méi)有真正刪除)

for((i=1;i<=${threads};i++))
do
    echo >&100  #echo默認(rèn)輸出一個(gè)空行,這里循環(huán)執(zhí)行,相當(dāng)于給該文件輸入了50個(gè)空行
done

for item in xxx
do
    read -u100  #從該文件中讀一行,如果沒(méi)有就會(huì)卡在這里。相當(dāng)于開啟一個(gè)線程。
    {
        耗時(shí)操作
        echo >&100  #執(zhí)行完任務(wù)后,輸入一行到該文件。相當(dāng)于釋放一個(gè)線程。
    }&
done
wait

exec 100>&- #關(guān)閉fd100

從上面的代碼和注釋應(yīng)該可以看的很清楚,其實(shí)控制進(jìn)程數(shù)量的方法就是控制向fifo文件中讀寫行。
至于為什么使用fifo文件,而不是使用普通文件。我查了一些文章以后發(fā)現(xiàn),在默認(rèn)情況下,fifo文件是阻塞的。
也就是說(shuō),如果fifo文件中沒(méi)有數(shù)據(jù),read是會(huì)卡住的,所以必須要使用fifo。實(shí)際上,fifo文件是進(jìn)程間通信的一種重要手段,有興趣的同學(xué)一定要深入看一看。

4. 番外篇(原子操作)

為什么會(huì)有這個(gè)番外篇?實(shí)際上是在工作中遇到一個(gè)需求,就是在耗時(shí)操作之后,我要打印進(jìn)度。但是打印進(jìn)度這個(gè)事情,無(wú)論如何也不可能是原子操作,那就會(huì)出現(xiàn)線程安全問(wèn)題。所以,我必須找到一種方法,可以實(shí)現(xiàn)一整塊代碼的原子操作。
那就是,加鎖。

# 以下是臨界區(qū)
(
    flock -x 7 7>&7  #flock文件鎖,-x表示獨(dú)享鎖
    打印進(jìn)度
)7<>temp.lock

【后記】

感謝大佬們的觀看,如果有不懂的地方可以隨時(shí)騷擾我。
如果發(fā)現(xiàn)錯(cuò)誤或可以改進(jìn)的地方,也希望大佬們不吝賜教,多謝。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.內(nèi)存的頁(yè)面置換算法 (1)最佳置換算法(OPT)(理想置換算法):從主存中移出永遠(yuǎn)不再需要的頁(yè)面;如無(wú)這樣的...
    杰倫哎呦哎呦閱讀 3,588評(píng)論 1 9
  • 又來(lái)到了一個(gè)老生常談的問(wèn)題,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢? 今天就這個(gè)問(wèn)題開始,來(lái)談?wù)劜?..
    tangsl閱讀 4,317評(píng)論 0 23
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,639評(píng)論 1 32
  • Java-Review-Note——4.多線程 標(biāo)簽: JavaStudy PS:本來(lái)是分開三篇的,后來(lái)想想還是整...
    coder_pig閱讀 1,772評(píng)論 2 17
  • 《一支口紅的秋色》 九月的雨飄過(guò) 大地流淌著一抹色 楓葉掩藏不住的緋紅 深深吻過(guò)大地的唇 依依的秋風(fēng) 尋找著華爾茲...
    奮小青柑閱讀 5,470評(píng)論 134 221

友情鏈接更多精彩內(nèi)容