[英]Multithreading Bash If Statements
What is the correct way to multithread independent if
statements in a bash script? 在bash脚本中多线程独立if
语句的正确方法是什么? Is it best to place the &
after code contained in the if
or after the expression? 难道最好将&
在所包含的代码之后if
还是表达后?
For an &
after the expression, it makes sense to continue threading as necessary if the if
contains a large block of code. 对于表达式之后的&
,如果if
包含大块代码, if
根据需要继续进行线程化是有意义的。 But should one line of code also end with &
? 但是,如果一行代码也以&
结尾?
After the expression: 表达后:
if [ expression ] &
then
#task
fi
After the task: 完成任务后:
if [ expression ]
then
#task &
fi
Imagine 3 if
statements that all perform tasks independent of each other, how does the execution work with the different placement of the &
? 想象一下, if
所有执行任务的语句彼此独立,那么执行如何与&
的不同位置一起工作? From what I understand, if placed after the expression, all 3 expressions start (basically) simultaneously and so do the 3 tasks. 根据我的理解,如果放在表达式之后,所有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 placed after the task code, the first if
would be evaluated and only as the first task begins would the 2nd if
be evaluated. 如果放在任务代码之后,第一if
将被评估,仅作为第一个任务开始将2号if
进行评估。 The tasks are more staggered than simultaneous. 这些任务比同步更加错开。
#Thread 1 #Thread 2 #Thread 3
if [ expr1 ]
then
task1 & if [ expr2 ]
fi then
task2 & if [ expr3 ]
fi then
task3 &
fi
wait
The expressions cannot be combined to do threading inside the if
such as: 表达式不能组合在if
进行线程化,例如:
if [ combined expression ]
then
#task1 &
#task2 &
#task3 &
fi
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
. 如果你希望每个if
条件在它各自的“线程”(实际上是子shell进程)的上下文中执行,那么我认为要做的是将每个if
的结束fi
语句后面的&
。 Then the evaluation of each if
expression, along with conditional code wiil occur entirely within the context of its own "thread". 然后,每个if
表达式的评估以及条件代码将完全在其自己的“线程”的上下文中发生。
For example: 例如:
#/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
Output from each "thread" is interleaved as expected: 每个“线程”的输出按预期交错:
1
a
2
b
3
c
Note in all cases with &
, these are actually processes (created with fork()
) and not threads (created with pthread_create()
). 注意在所有情况下使用&
,这些实际上是进程(使用fork()
创建)而不是线程(使用pthread_create()
创建)。 See Multithreading in Bash . 请参阅Bash中的多线程 。 You can test this by creating a variable, eg n=0
before the "threads" are started. 您可以通过创建变量来测试这一点,例如在“线程”启动之前n=0
。 Then in one thread increment n and echo $n in all threads. 然后在一个线程中增加n并在所有线程中回显$ n。 You'll see each "thread" gets its own copy of n - n will have different values in the incrementing and non-incrementing threads. 您将看到每个“线程”获得自己的n - n副本将在递增和非递增线程中具有不同的值。 fork()
creates a new process copy (including independent copies of variables); fork()
创建一个新的流程副本(包括变量的独立副本); pthread_create()
doesn't. pthread_create()
没有。
Placing the &
after the if
will only background the evaluation of the conditional expression ; 放置&
后if
将只背景条件表达式的评估; [
is actually an alias for the test
command, and that is what will be backgrouded, and not the task. [
实际上是test
命令的别名,这将是背景,而不是任务。
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
在何种程度上的任务是交错的,而不是同时取决于评估所需要的相对时间expr1
比执行所需的时间task1
See the following script: 请参阅以下脚本:
#!/bin/bash
if [ 1 ] &
then
sleep 10
fi
if [ 1 ] &
then
sleep 10
fi
if [ 1 ] &
then
sleep 10
fi
wait
it takes 30 seconds to run 它需要30秒才能运行
$ time . test.sh
[3] Done [ 1 ]
[3] Done [ 1 ]
[3] Done [ 1 ]
real 0m30.015s
user 0m0.003s
sys 0m0.012s
and you see that the backgrounded task is [ 1 ]
, not sleep
. 你看到后台任务是[ 1 ]
,而不是sleep
。 Note that is is meaningless as explained by @chepner. 注意,如@chepner所解释的那样没有意义。
Now the other case: 现在另一个案例:
#!/bin/bash
if [ 1 ]
then
sleep 10 &
fi
if [ 1 ]
then
sleep 10 &
fi
if [ 1 ]
then
sleep 10 &
fi
wait
gives: 得到:
[2] Done sleep 10
[3] Done sleep 10
[4]- Done sleep 10
real 0m10.197s
user 0m0.003s
sys 0m0.014s
It only takes 10 seconds ; 它只需要10秒钟; all the sleeps
are simultaneous as they are being backgrounded. 所有的sleeps
是同时的,因为它们是背景的。
Last option as described by @DigitalTrauma: @DigitalTrauma描述的最后一个选项:
#!/bin/bash
if [ 1 ]
then
sleep 10
fi &
if [ 1 ]
then
sleep 10
fi &
if [ 1 ]
then
sleep 10
fi &
wait
Then the whole if
statement is backgrounded, ie both the evaluation of exprN
and of taskN
然后整个if
语句是后台的,即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
giving the expected 10 seconds running time 给出预期的10秒运行时间
Compare 相比
if false
then
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. 命令&
以状态0立即退出&
退出,因此无论后台进程最终返回什么,都会执行if
分支。 It doesn't make sense to put a command that unconditionally succeeds in the command list of an if
statement. 将无条件成功的命令放在if
语句的命令列表中是if
。 You have to let it complete so the body can be correctly (conditionally) executed. 你必须让它完整,以便正确(有条件地)执行身体。
the answers so far rely on using spawning 3 and waiting for all 3 to complete before starting again. 到目前为止,答案依赖于使用产卵3并等待所有3完成再开始之前。
a "better" way in bash is using the jobs
command like so bash中的“更好”方式就是使用jobs
命令
jobs|wc -l
and then looping with a small sleep command like so jobs|wc -l
然后使用像这样的小睡眠命令循环
(not tested code) (未测试代码)
while [ $COUNTER -lt 10 ]; do
if [[$(jobs | wc-l`) < 3 ]] then
expression &
fi
sleep 10;
done
that will allow all 3 "threads" to be filled without waiting for all 3 to complete before refilling 这将允许所有3个“线程”被填充,而无需等待所有3个完成再填充之前完成
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.