The interesting thing about workflow is the ability to perform tasks in parallel. It is an essential feature, but it is a bit complex.
Splits are not very difficult. Once a task is completed, the following steps are looked up in the process definition. If there is more than one step that immediately follows the completed step, it is determined which of the steps will be activated.
For joins it is somewhat more complicated. The joins are also defined in the process definition, but in order to determine if the conditions of the join are satisfied, other active steps that can lead to the join have to be found.
In the following picture, a case is given. The circles are the steps of the proces. The filled circles are active tasks for the case.
For example: step 11 is completed. The next step is 14. We can see that there is another step that comes before step 14: step 12. So we have to find out if there is still an active task that can lead to step 12. This is not so difficult. We go back from step 12 until we find a split and take note of all the active tasks we find.
If we would do the same exercise starting from step 15 we would encounter the join in step 14 before we find the split in step 4. In that case, we cannot stop in step 4, but we have to back to step 2.
In other words we have to go back until we find a split, but for each join we encounter, we have to go back one split further.
For this reason, every split must correspond with a join and vice versa. For example you cannot eliminate the join in step 13, and join step 9, 10 and 14 in step 15.
This is not a very fast way of working at run-time. Therefore, this algorithm is only used at design time, for checking the soundness of the process definition. At run time, a much simpler approach is taken. When a split is encountered, it is determined which of the possible steps will be activated. So at that time, it is known how many steps will eventually lead to the join. For example: if the split in step 2 is an AND split, tasks 3 and 4 will be activated. So the join in step 15 should wait for the two preceding steps to complete.