I have some background in Petri nets, and in my last UML training, the trainer explained how activity diagrams are essentially a form of a Petri net with Petri net semantics.

Now read that fork and join symbols are used for modelling concurrency in UML activity diagrams, and I am a bit unsure whether they are actually necessary or whether they serve a deeper purpose.

It seems like a fork could just be replaced by a no-op Action that relays from one incoming link to many outgoing ones. Same goes for a join node, which could be replaced by a no-op node that syncs the incoming arrows. Many times, the no-op action could be eliminated by directly attaching the arrows to the action leading up to the fork or following the "join".

The only thing that might indicate the necessity for a join node would be the "join specification", but that seems like an infrequent use case.

Here is an example of a petri-net evaluation without forks and joins:

an example of a petri-net evaluation without forks and joins

  • 1
    Maybe I'm just not familiar enough with Petri nets but can you explain what you believe is the distinction between a 'join' and a 'no-op node that syncs the incoming arrows'?
    – JimmyJames
    Oct 25 '18 at 13:42
  • Something along these lines imgur.com/a/81SpLsn From what i have been told, the places for the marks are not displayed in UML, but implicitly assumed in the arrows. You see the evaluation of the petrin net in that diagram
    – wirrbel
    Oct 25 '18 at 17:28
  • I'm struggling to get past the jargon but it seems to me that if you don't have some sort of way of specifying fork-join but allow for it, you have no way to specify things that are not fork-join e.g. sequential execution of branches. You also can't allow for join points that are later in the execution that where the paths intersect.
    – JimmyJames
    Oct 25 '18 at 21:50

Normally there is only a single active state. Fork creates more active states that can then propagate independently.

There is one thing you are missing with regard to join: you can only pass join when all inputs are incoming. That cannot be modeled simply by more incoming connections.

You can perfectly model the states between fork and join by doing a Cartesian product between and then exhaustively modeling all the transitions between them.

Fork and join simplify the diagram by keeping the logical states of each part visible.


The UML specification https://www.omg.org/cgi-bin/doc?formal/17-12-05.pdf states

As an ActivityNode may be the source for multiple ActivityEdges, the same token can be offered to multiple targets. However, the same token can only be accepted at one target at a time (unless it is copied, whereupon it is not the same token, see ForkNodes in sub clause 15.3 and ExecutableNodes in sub clause 15.5). If a token is offered to multiple ActivityNodes at the same time, it shall be accepted by at most one of them, but exactly which one is not completely determined by the Activity flow semantics.

In other words, the UML specifies that tokens are not copied by default. Copying of tokens by default is what I assumed from my previous exposures to Petri nets.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.