多线程Bash如果声明

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)

Dig*_*uma 6

如果您希望每个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()没有.


dam*_*ois 5

放置&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秒运行时间