by Michael Bevilacqua-Linn
In the previous chapter, we learned about Clojure’s take on value, state, and identity. In this chapter, we’ll take things a bit further and see how Clojure’s philosophy makes it ideal for concurrent programming. As we do so, we’ll take a closer look at Clojure’s managed references—atoms, agents, and refs—as well as the software transactional memory system they work with.
A concurrent program is one where multiple processes, or threads, may be run in parallel. The main difficulty with concurrent programming is coordinating access to shared resources. As we’ll see, this can have strange effects even in seemingly simple situations.
Let’s start off with a look at a simple concurrent programming problem in Java. We just want to increment counters from multiple threads running concurrently. We use two counters: the first is a plain old int, and the second is a much more impressive sounding AtomicInteger.