Mat*_*att 7 unix linux bash multithreading
if在bash脚本中多线程独立语句的正确方法是什么?是否最好将&after代码放在if表达式中或表达式之后?
对于&表达式之后,如果if包含大块代码,则根据需要继续进行线程化是有意义的.但是,一行代码也应该结束&吗?
表达后:
if [ expression ] &
then
#task
fi
Run Code Online (Sandbox Code Playgroud)
完成任务后:
if [ expression ]
then
#task &
fi
Run Code Online (Sandbox Code Playgroud)
想象一下if,所有3个语句都执行彼此独立的任务,执行如何与不同的位置一起工作&?根据我的理解,如果放在表达式之后,所有3个表达式(基本上)同时启动,3个任务也是如此.
#Thread 1 #Thread 2 #Thread 3
if [ expr1 ] & if [ expr2 ] & if [ expr3 ] &
then then then
task1 task2 task3
fi fi fi
wait
Run Code Online (Sandbox Code Playgroud)
如果放在任务代码之后,if将评估第一个任务代码,并且仅在第一个任务开始时才评估第二个任务代码if.这些任务比同步更加错开.
#Thread 1 #Thread 2 #Thread 3
if [ expr1 ]
then
task1 & if [ expr2 ]
fi then
task2 & if [ expr3 ]
fi then
task3 &
fi
wait
Run Code Online (Sandbox Code Playgroud)
表达式不能组合在一起进行线程化,if例如:
if [ combined expression ]
then
#task1 &
#task2 &
#task3 &
fi
Run Code Online (Sandbox Code Playgroud)
如果您希望每个if条件在其各自的"线程"(实际上是子shell进程)的上下文中执行,那么我认为要做的是将每个条件放在&结束fi语句之后if.然后,每个if表达式的评估以及条件代码将完全在其自己的"线程"的上下文中发生.
例如:
#/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
Run Code Online (Sandbox Code Playgroud)
每个"线程"的输出按预期交错:
1
a
2
b
3
c
Run Code Online (Sandbox Code Playgroud)
请注意,在所有情况下&,这些实际上是进程(使用fork())创建而不是线程(使用创建pthread_create()).请参阅Bash中的多线程.您可以通过创建变量来测试这一点,例如n=0在"线程"启动之前.然后在一个线程中增加n并在所有线程中回显$ n.您将看到每个"线程"获得自己的n - n副本将在递增和非递增线程中具有不同的值. fork()创建一个新的流程副本(包括变量的独立副本); pthread_create()没有.
放置&后if只会背景条件表达式的评估; [实际上是test命令的别名,这将是背景,而不是任务.
放置&任务后将完成任务.任务交错而不是同步的程度取决于expr1与执行所需时间相比评估所需的相对时间task1
请参阅以下脚本:
#!/bin/bash
if [ 1 ] &
then
sleep 10
fi
if [ 1 ] &
then
sleep 10
fi
if [ 1 ] &
then
sleep 10
fi
wait
Run Code Online (Sandbox Code Playgroud)
它需要30秒才能运行
$ time . test.sh
[3] Done [ 1 ]
[3] Done [ 1 ]
[3] Done [ 1 ]
real 0m30.015s
user 0m0.003s
sys 0m0.012s
Run Code Online (Sandbox Code Playgroud)
而且你看到背景任务是[ 1 ],而不是sleep.注意,如@chepner所解释的那样没有意义.
现在另一个案例:
#!/bin/bash
if [ 1 ]
then
sleep 10 &
fi
if [ 1 ]
then
sleep 10 &
fi
if [ 1 ]
then
sleep 10 &
fi
wait
Run Code Online (Sandbox Code Playgroud)
得到:
[2] Done sleep 10
[3] Done sleep 10
[4]- Done sleep 10
real 0m10.197s
user 0m0.003s
sys 0m0.014s
Run Code Online (Sandbox Code Playgroud)
它只需要10秒钟; 所有这些sleeps都是同时的,因为它们是背景的.
@DigitalTrauma描述的最后一个选项:
#!/bin/bash
if [ 1 ]
then
sleep 10
fi &
if [ 1 ]
then
sleep 10
fi &
if [ 1 ]
then
sleep 10
fi &
wait
Run Code Online (Sandbox Code Playgroud)
然后整个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
Run Code Online (Sandbox Code Playgroud)
给出预期的10秒运行时间