Многопоточные Операторы Bash If
каков правильный способ многопоточного независимого if
операторы в сценарии bash? Лучше всего разместить &
после кода, содержащегося в if
или после выражения?
на &
после выражения имеет смысл продолжить резьбу по мере необходимости, если if
содержит большой блок кода. Но если одна строка кода заканчивается &
?
после выражения:
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
будет оцениваться и только как начинается первая задача будет 2nd 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
4 ответов
если вы хотите, чтобы каждый if
условие для выполнения в контексте его соответствующего "потока" (на самом деле процесс subshell), то я думаю, что нужно сделать, это поставить &
после закрытия fi
заявление для каждого if
. Тогда оценка каждого 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()
). См. многопоточность в Bash. Вы можете проверить это, создав переменную, например n=0
перед запуском" потоков". Затем в одном потоке инкремент n и Эхо $n во всех потоках. Вы увидите, что каждый "поток" получает свою собственную копию n - n будет иметь разные значения в увеличивающихся и не увеличивающихся потоках. fork()
создает новую копию процесса (включая независимые копии переменных);pthread_create()
нет.
помещения &
после if
будет только фон оценки условного выражения;[
на самом деле псевдоним , а вот что будет backgrouded, а не задача.
помещения &
после задачи будет фон задачи. Степень, в которой задачи расположены в шахматном порядке, а не одновременно, зависит от относительного времени, необходимого для оценки expr1
по сравнению со временем, необходимым для выполнения task1
см. следующий сценарий:
#!/bin/bash
if [ 1 ] &
then
sleep 10
fi
if [ 1 ] &
then
sleep 10
fi
if [ 1 ] &
then
sleep 10
fi
wait
для запуска требуется 30 секунд
$ 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
выдает:
[2] Done sleep 10
[3] Done sleep 10
[4]- Done sleep 10
real 0m10.197s
user 0m0.003s
sys 0m0.014s
это занимает всего 10 секунд ; все sleeps
одновременны по мере того как они backgrounded.
последний вариант описано @DigitalTrauma:
#!/bin/bash
if [ 1 ]
then
sleep 10
fi &
if [ 1 ]
then
sleep 10
fi &
if [ 1 ]
then
sleep 10
fi &
wait
тогда все if
утверждение является backgrounded, т. е. как оценка 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
дает ожидаемых 10 секунд времени
сравнить
if false
then
echo "condition true"
fi
С
if false &
then
echo "condition ... true?"
fi
команда расторгнут &
немедленно выходит со статусом 0, поэтому if
филиала принимается независимо от того, что фоновый процесс в конечном итоге возвращается. Не имеет смысла помещать команду, которая безоговорочно преуспевает в списке команд if
заявление. Вы должны позволить ему завершить, чтобы тело могло быть правильно (условно) выполнено.
ответы до сих пор полагаются на использование нереста 3 и ждут завершения всех 3, прежде чем начать снова.
"лучший" способ в bash использует jobs
команда типа so
jobs|wc -l
а затем цикл с небольшой командой сна, как так
(не проверял код)
while [ $COUNTER -lt 10 ]; do
if [[$(jobs | wc-l`) < 3 ]] then
expression &
fi
sleep 10;
done
Это позволит заполнить все 3 "потока", не дожидаясь завершения всех 3 перед заправкой