Bash shell basics — synchronous or asynchronous

Paul Guerin
3 min readJun 3, 2023

There is alot of confusion about the differences between synchronous and asynchronous processing.

The easiest way to describe the difference between those types is to create some examples.

In the Bash shell its fairly easy to create a general purpose workload that involves some CPU processing and some waiting for an event.

Synchronous processing

A workload with some waiting can be simulated with the sleep command and a simple For loop.

Execute a simple job such as the following, where a 5 second task is executed 5 times.

#!/bin/bash

#function fcpu {
# for i in {1..350000} ; do >null ; done
#}

function fwait {
sleep 5
}

main() {
local start=$(date +%s)

for x in {1..5}
do
fwait
#fcpu
#
# the following is equivalent syntax
#(fwait)
#(fcpu)
#
# process status with an asci forest tree diagram
ps -fTo pid,comm,psr,etimes
done

local end=$(date +%s)
echo $((end-start))
}

main

# Print the accumulated user and system times for the shell
# and for processes run from the shell.
times

exit

The Ps command in the script will show the logical core used (PSR column) for the process (PID column) and the elapsed time.

tail of the output

The execution was performed synchronously which means that only a single logical core of the CPU was used (even though the CPU of my hardware has 8 logical cores).

For this script, the 5 second task executed for 5 times and takes an elapsed time of 25 seconds.

But synchronous processing isn’t the only option.

Asynchronous processing

If there is a job with many tasks, and the tasks don’t have dependencies with one another, then asynchronous processing becomes an option.

In Bash, asynchronous processing is invoked in a subshell environment. Subshells are deployed using the ‘&’ character.

An example of asynchronous processing is below:

#!/bin/bash

#function fcpu {
# for i in {1..350000} ; do >null ; done
#}

function fwait {
sleep 5
}

main() {
local start=$(date +%s)

for x in {1..5}
do
fwait&
#fcpu&
#
# the following is equivalent syntax
#(fwait)&
#(fcpu)&
#
# process status with an asci forest tree diagram
ps -fTo pid,comm,psr,etimes
done

echo 'wait for completion of the asynch jobs...'
wait

local end=$(date +%s)
echo $((end-start))
}

main

# Print the accumulated user and system times for the shell
# and for processes run from the shell.
times

exit
tail of the output

The execution was performed asynchronously which means that any the logical cores of the CPU were used for each task.

For this asynchronous processing script the 5 second task executed for 5 times only takes an elapsed time of 5 seconds.

--

--