The STM isn't safe for side effects. Because a dosync
block may get retried, possibly more than once, any side effects may be executed again and again, whether they should be or not. Values may get written to the screen or logfile multiple times. Worse, values may be written to the database more than once.
However, all programs must produce side effects. The trick is adding them while keeping a handle on complexity. The easiest way to do that is to keep side effects out of transactions.
For this recipe, to illustrate what can happen, we'll simulate thread starvation. That sounds serious. It just means that one thread isn't able to access the resources it needs, so it can't do its job. We'll also use an atom —a reference that isn't controlled by the STM—to keep track of how many times the STM retries a call to an agent. That way, we can see what creates the problem, and what we need to do to fix it.