I have written 3 shell scripts named s1.sh s2.sh s3.sh. They have the same content:
#!/bin/ksh
echo $0 $$
and s.sh invoke them in order:
<
The process scheduler achieves apparent multitasking by running a snippet of each task at a time, then rapidly switching to another. Depending on system load, I/O wait, priority, scheduling algorithm etc, two processes started at almost the same time may get radically different allotments of the available CPU. Thus there can be no guarantee as to which of your three processes reaches its echo statement first.
This is very basic Unix knowledge; perhaps you should read a book or online tutorial if you mean to use Unix seriously.
If you require parallel processes to execute in a particular order, use a locking mechanism (semaphore, shared memory, etc) to prevent one from executing a particular part of the code, called a "critical section", before another. (This isn't easy to do in shell script, though. Switch to Python or Perl if you don't want to go all the way to C. Or use a lock file if you can live with the I/O latency.)
In your second example, the exec command replaces the current process with another. Thus s1 takes over completely, and the commands to start s2 and s3 are never seen by the shell.
(This was not apparent in your first example because the & caused the shell to fork a background process first, basically rendering the exec useless anyway.)