The function passed to swap!
may be called multiple times if there are multiple threads contending to modify the Atom. As long as it is free of side-effects, however, only the return of the final call will be reflected in the Atom's causal history.1
Here's one possible scenario:
Thread 1 attempts
(swap! atomic-clock inc)
.Thread 2 attempts the same.
Thread 2 manages to perform its
swap!
first.Thread 1 attempts a compare-and-swap on the atom and fails, because its notion of the original value is now out of date.
Thread 1 retries and successfully commits.
Here there are three calls to inc
, two on thread 1, one on thread 2.
The fact that inc
is not idempotent is not a problem.
1 Considered abstractly; Clojure does not actually store history information for Atoms.