Multithreading Bash If Statements Multithreading Bash If Statements multithreading multithreading

Multithreading Bash If Statements


If you want each if condition to execute within the context of its respective "thread" (actually subshell process), then I think the thing to do is put the & after the closing fi statement for each if. Then the evaluation of each if expression, along with conditional code wiil occur entirely within the context of its own "thread".

For example:

#/bin/bashif [ 1 ]   then    for i1 in {1..3}; do echo $i1; sleep 1; donefi &if [ 1 ]  then    for i2 in {a..c}; do echo $i2; sleep 1; donefi &wait

Output from each "thread" is interleaved as expected:

1a2b3c

Note in all cases with &, these are actually processes (created with fork()) and not threads (created with pthread_create()). See Multithreading in Bash. You can test this by creating a variable, e.g. n=0 before the "threads" are started. Then in one thread increment n and echo $n in all threads. You'll see each "thread" gets its own copy of n - n will have different values in the incrementing and non-incrementing threads. fork() creates a new process copy (including independent copies of variables); pthread_create() doesn't.


Placing the & after the if will only background the evaluation of the conditional expression ; [ is actually an alias for the test command, and that is what will be backgrouded, and not the task.

Placing the & after the task will background the task. The degree to which the tasks are staggered rather than simultaneous depends on the relative time needed to evaluate expr1 compared to the time needed to perform task1

See the following script:

#!/bin/bashif [ 1 ] &then    sleep 10 fiif [ 1 ] &then    sleep 10 fiif [ 1 ] &then    sleep 10 fiwait

it takes 30 seconds to run

$ time . test.sh [3]   Done                    [ 1 ][3]   Done                    [ 1 ][3]   Done                    [ 1 ]real    0m30.015suser    0m0.003ssys 0m0.012s

and you see that the backgrounded task is [ 1 ], not sleep. Note that is is meaningless as explained by @chepner.

Now the other case:

#!/bin/bashif [ 1 ] then    sleep 10 &fiif [ 1 ] then    sleep 10 &fiif [ 1 ] then    sleep 10 &fiwait

gives:

[2]   Done                    sleep 10[3]   Done                    sleep 10[4]-  Done                    sleep 10real    0m10.197suser    0m0.003ssys 0m0.014s

It only takes 10 seconds ; all the sleeps are simultaneous as they are being backgrounded.

Last option as described by @DigitalTrauma:

#!/bin/bashif [ 1 ] then    sleep 10 fi &if [ 1 ]then    sleep 10 fi &if [ 1 ] then    sleep 10fi &wait

Then the whole if statement is backgrounded, i.e. both the evaluation of exprN and of taskN

[3]   Done                    if [ 1 ]; then    sleep 10;fi[4]   Done                    if [ 1 ]; then    sleep 10;fi[5]   Done                    if [ 1 ]; then    sleep 10;fireal    0m10.017suser    0m0.003ssys 0m0.013s

giving the expected 10 seconds running time


Compare

if falsethen  echo "condition true"fi

with

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

A command terminated by & exits immediately with status 0, so the if branch is taken regardless of what the background process eventually returns. It doesn't make sense to put a command that unconditionally succeeds in the command list of an if statement. You have to let it complete so the body can be correctly (conditionally) executed.