I am just going through Clojure Koans and I am now playing with atoms. My question is not related to Koans, but a general one.
Consider the following (shortened) example from Koans:
(def atomic-clock (atom 0))
(meditations
(= 1 (do
(swap! atomic-clock inc)
@atomic-clock)))
The documentation for swap! states that the function it is applied to (inc
in this case) could be called multiple times and thus the function should be free from side effect.
Obviously, inc
is free from side effects, but is not idempotent. Does this mean, that the assertion above may actually still fail? I.e. that in the case the function is indeed called multiple times, the value of the atom is incremented more than once?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With