2013-10-18 9 views
7

マルチスレッドの独立したifステートメントをbashスクリプトで使用する正しい方法は何ですか? ifに含まれるコードの後、または式の後に&を配置するのが最善でしょうか?マルチスレッドBashの場合ステートメント

式の後に&の場合、ifに大きなコードブロックが含まれている場合は、必要に応じてスレッドを続行することが理にかなっています。しかし、1行のコードも&で終わるべきですか?式の後

:タスクの後

if [ expression ] & 
    then 
    #task 
fi 

if [ expression ] 
    then 
    #task & 
fi 


は、すべての異なる配置と実行の作業を行う方法を、互いに独立したタスクを実行することを3つのif文を想像してみて&?私が理解していることから、式の後に置くと、3つの式はすべて(基本的に)同時に開始し、3つのタスクも実行します。タスクコードの後に​​置かれた場合

#Thread 1   #Thread 2   #Thread 3 
if [ expr1 ] & if [ expr2 ] & if [ expr3 ] & 
    then    then    then 
    task1   task2   task3 
fi    fi    fi 
wait 

、最初ifが評価されるであろうと最初のタスクは、第2 ifが評価されるであろうから始まりとしてのみ。タスクは、同時よりもずらされています。

#Thread 1   #Thread 2   #Thread 3 
if [ expr1 ] 
    then 
    task1 &  if [ expr2 ] 
fi     then 
         task2 &  if [ expr3 ] 
        fi     then 
             task3 & 
            fi 
wait 

内部スレッドを実行するために組み合わせることがないできifなど:

if [ combined expression ] 
    then 
    #task1 & 
    #task2 & 
    #task3 & 
fi 

答えて

6

ifの各条件を実行する場合それぞれの "スレッド"(実際にサブシェルプロセス)のコンテキスト内で、私は行うことは、それぞれのifのためにfiの終了の後に&を置くと思う。次に、各if式の評価は、条件付きコードwiilとともに、それ自体の「スレッド」のコンテキスト内で完全に発生する。

例えば:予想通り、それぞれ "スレッド" から

#/bin/bash 

if [ 1 ] 
    then 
    for i1 in {1..3}; do echo $i1; sleep 1; done 
fi & 
if [ 1 ] 
    then 
    for i2 in {a..c}; do echo $i2; sleep 1; done 
fi & 
wait 

出力はインターリーブさ:&と、すべての場合において

1 
a 
2 
b 
3 
c 

注、これらは実際には(fork()で作成された)プロセスとされませんスレッド(pthread_create()で作成)。 Multithreading in Bashを参照してください。これをテストするには、変数を作成します(例: "スレッド"が開始される前にn=0。次に、あるスレッドでは、すべてのスレッドでnとecho $ nをインクリメントします。それぞれの "スレッド"が独自のn - nのコピーを取得すると、増分スレッドと非増分スレッドで異なる値が設定されます。 fork()は、新しいプロセスコピー(変数の独立したコピーを含む)を作成します。 pthread_create()はありません。

+0

私の特定のケースでは、それらは別個のプロセスであることを示します。終了したら子プロセスを終了するだけですか? – Matt

+1

かなり、そうです。 'wait'はすべての子サブプロセスが完了するまでブロックします。したがって、 'wait'の後にさらにステートメントがある場合、これらのステートメントはすべてのサブプロセスが完了するまで実行されません。特定のサブプロセスが終了するのを待つ場合は、 'wait'はpidまたはjob idを取ることもできます。 '&'でバックグラウンドした直後に、組み込みの '$!'変数からサブプロセスのPIDを得ることができます。 –

5

配置&ifする唯一背景条件式の評価後、 [は、実際にはtestコマンドのエイリアスです。これはバックグラウンドであり、タスクではありません。

タスクの後に&を配置すると、そのタスクがバックグラウンドになります。それが実行に30秒かかり

#!/bin/bash 

if [ 1 ] & 
then 
    sleep 10 
fi 
if [ 1 ] & 
then 
    sleep 10 
fi 
if [ 1 ] & 
then 
    sleep 10 
fi 
wait 

:タスクは千鳥ではなく、同時である度合いはtask1

次のスクリプトを参照してくださいを実行するのに必要な時間に比べexpr1を評価するために必要な相対的な時間に依存します

$ time . test.sh 
[3] Done     [ 1 ] 
[3] Done     [ 1 ] 
[3] Done     [ 1 ] 

real 0m30.015s 
user 0m0.003s 
sys 0m0.012s 

、あなたがバックグラウンドにタスクが[ 1 ]、ないsleepであることがわかります。 @chepnerで説明されているように意味がないことに注意してください。今

その他の場合:

#!/bin/bash 

if [ 1 ] 
then 
    sleep 10 & 
fi 
if [ 1 ] 
then 
    sleep 10 & 
fi 
if [ 1 ] 
then 
    sleep 10 & 
fi 
wait 

ができます:それはわずか10秒かかり

[2] Done     sleep 10 
[3] Done     sleep 10 
[4]- Done     sleep 10 

real 0m10.197s 
user 0m0.003s 
sys 0m0.014s 

sleepsはすべて、背景として同時に表示されます。

@DigitalTraumaによって記載されているように最後のオプション:全体if文がバックグラウンドにされた後

#!/bin/bash 

if [ 1 ] 
then 
    sleep 10 
fi & 
if [ 1 ] 
then 
    sleep 10 
fi & 
if [ 1 ] 
then 
    sleep 10 
fi & 
wait 

、時間を実行していると予想10秒与えるすなわち両方exprNの評価とtaskN

[3] Done     if [ 1 ]; then 
    sleep 10; 
fi 
[4] Done     if [ 1 ]; then 
    sleep 10; 
fi 
[5] Done     if [ 1 ]; then 
    sleep 10; 
fi 

real 0m10.017s 
user 0m0.003s 
sys 0m0.013s 

4

if false & 
then 
    echo "condition ... true?" 
fi 

状態0でただちに&終了で終了し、そうif分岐は関係なく、バックグラウンド・プロセスが最終的に返すものの取られるコマンドで

if false 
then 
    echo "condition true" 
fi 

を比較します。無条件に成功するコマンドをifステートメントのコマンドリストに入れることは意味がありません。ボディを正しく(条件付きで)実行できるように、それを完了させる必要があります。

+0

私はそれが起こるかどうか疑問に思った。私は '&'は次のコード行に進むと思ったが、次の行は '' f'の後にあると思った。私はDigitalTraumaの答えがまだ評価されることを許可すると思います。 – Matt

+0

はい、彼の答えは正しいです。これは、あなたが条件を背景にすることができない理由の説明に過ぎません。 – chepner

0

これまでの回答は、産卵3を使用し、すべての3が完了するのを待ってから再開します。

bashで「良好」な方法は、そう

jobs|wc -lようjobsコマンドを使用してそのように

(テストしていないコード)

while [ $COUNTER -lt 10 ]; do 
if [[$(jobs | wc-l`) < 3 ]] then 

    expression & 
    fi 
    sleep 10; 

done 

ような小休止コマンドでループされます補充する前にすべての3が完了するのを待たずに3つの「スレッド」をすべて埋めることができます

関連する問題