Patterns, properties, and design intuition — the middle ground between "what is a place" and "solve it with ODEs."
The stoplight uses a single token cycling through three places. It's a state machine — exactly one state is active at any time. Simple and predictable.
But what happens when you add a second token? Now two things are true at once. Two places are occupied. Multiple transitions might be enabled simultaneously. This is concurrency — and it's the reason Petri nets exist.
Flowcharts can't express concurrency. They follow a single thread of execution. Petri nets track all tokens simultaneously, making it natural to model parallel activities, shared resources, and synchronization.
Every pattern below emerges from how tokens interact with transitions. One token gives you a state machine. Many tokens give you a concurrent system.
A single token cycles through places. Each place represents one state; each transition represents one event. Only one state is active at a time.
This is the simplest Petri net pattern. If you've used finite automata or state charts, this is the same idea but drawn differently.
One transition produces tokens in multiple output places. Those tokens then move independently — parallel activities have begun.
In workflow terms, this is a parallel gateway. One event triggers two (or more) things that happen concurrently.
A transition requires tokens from multiple input places. It only fires when all inputs are ready. This is how you wait for parallel tasks to complete before proceeding.
Fork and join together form the fork/join pattern — split work into parallel branches, then merge the results.
A place holds multiple tokens representing a shared resource with limited capacity (exam rooms, cups, forks, staff). Transitions consume a resource token to begin work and return it when done.
This naturally models capacity constraints. If the pool is empty, no transition consuming from it can fire — work waits.
See it: Coffee Shop (beans, milk, cups deplete and restock) → | Vet Clinic (exam rooms, DVMs, surgery suites) →Two or more transitions compete for the same resource token. Only one can win. The loser has to wait until the token is returned.
This is how Petri nets model locks, shared equipment, and turn-taking. The resource place acts as a mutex — exactly one consumer at a time.
See it: Dining Philosophers (adjacent philosophers share forks) →A producer adds tokens to a buffer. A consumer removes them. A counter place tracks remaining capacity. When the buffer is full (counter is zero), the producer blocks. When the buffer is empty, the consumer blocks.
The trick: use two places — buffer (how many items) and buffer_space (how much room). They always sum to the capacity.
Once you build a net, you want to know: does it behave well? Petri net theory gives precise names to the things that can go right or wrong.
| Property | What It Means | Example |
|---|---|---|
| Live | Every transition can eventually fire again, no matter what state you reach. Nothing is permanently disabled. | Stoplight — all three transitions keep cycling forever |
| Bounded | No place ever accumulates more than k tokens. Resources stay finite; memory stays bounded. | Producer-Consumer — buffer never exceeds 5 |
| Safe | A special case of bounded where k = 1. Each place holds at most one token. | Stoplight — each light is either on or off |
| Deadlock-free | The system can never reach a state where nothing can fire. It always has a next step. | Dining Philosophers — deliberately not deadlock-free |
| Reversible | From any reachable state, you can always get back to the initial state. | Stoplight — always returns to red |
The Petri Net Viewer's analysis tools check these automatically. Open any model in the viewer and the sidebar shows place/transition counts. Use the MCP tools (petri_analyze) for full reachability and deadlock analysis.
A deadlock happens when the system reaches a state where no transition can fire. Every transition is waiting for a token that will never come.
The Dining Philosophers demo is the classic example. Five philosophers sit around a table, each needing two forks to eat. Each fork is shared with a neighbor.
Deadlock requires four conditions (all must be true at once):
1. Mutual exclusion — resources can't be shared
2. Hold and wait — processes hold one resource while waiting for another
3. No preemption — resources can't be forcibly taken
4. Circular wait — a cycle of processes each waiting for the next
Break any one condition and deadlock becomes impossible.
This is one of the great strengths of Petri nets: deadlock isn't an abstract concept you reason about in your head. You can see it happen. Step through the transitions in the demo and watch the system freeze.
When you face a new problem, here's how to translate it into a Petri net:
Try it now. Open the empty canvas in the Petri Net Viewer. Model something simple: a vending machine (insert coin → select drink → dispense), a door lock (locked/unlocked with a key), or a two-player turn-taking game.
Work through the demos in this order. Each one introduces a new concept that builds on the previous ones.