The title of this essay is a bit tongue-in-cheek because, no matter how promising the new stalwart JVM languages (And here I’m thinking of the most promising of those languages, viz. Scala and Clojure) are with helping us manage concurrency, the fact is that Java is going to be around in a big way (for a long time, and that’s my two cents’ worth). In fact, the title of this essay (i.e. Java Concurrency in Retrospect) is in part a tribute to, and a spin on, the title of the amazingly rich and highly regarded book Java Concurrency in Practice, by Brian Goetz, et al.
I’ve focused a career on simplifying simple problems, but this book ambitiously and effectively works to simplify a complex but critical subject: concurrency. Java Concurrency in Practice is revolutionary in its approach, smooth and easy in style, and timely in its delivery—it’s destined to be a very important book.
1.1 Non-thread-safe sequence generator1.2 Thread-safe sequence generator2.1 A stateless servlet2.2 Servlet that counts requests without the necessary synchronization. Don’t do this.2.3 Race condition in lazy initialization. Don’t do this.2.4 Servlet that counts requests using AtomicLong2.5 Servlet that attempts to cache its last result without adequate atomicity. Don’t do this.2.6 Servlet that caches last result, but with unnacceptably poor concurrency. Don’t do this.2.7 Code that would deadlock if intrinsic locks were not re-entrant2.8 Servlet that caches its last request and result3.1 Sharing variables without synchronization. Don’t do this.3.2 Non-thread-safe mutable integer holder3.3 Thread-safe mutable integer holder3.4 Counting sheep3.5 Publishing an object……
Clojure is a dialect of Lisp directly supporting concurrent software development using functional programming techniques, and like the Lisp described in Beating the Averages, provides an environment conducive to agility. Clojure fosters agility in ways that many popular programming languages can’t. Many programming languages are bewitched with most or all of the following:
- Unavoidable boilerplate
- A long thought-code-feedback loop
- Incidental complexity
- Difficulties in extension
- Deficiencies in supporting crucial programming paradigms
- Only a handful of programmers know how to write a correct, concurrent application or program. The correctness of the program is important.
- Debugging multithreaded programs is difficult. The same program that causes deadlock in production might not have any locking issues when debugging locally. Sometimes threading issues show up after years of running in production.
- Threading encourages shared state concurrency, and it’s hard to make programs run in parallel because of locks, semaphores, and dependencies between threads.
On one side of the equation (italics are mine), Clojure utilizes Software Transactional Memory (STM), agents, a clear distinction between identity and value types, arbitrary polymorphism, and functional programming to provide an environment conducive to making sense of state in general, and especially in the face of concurrency. On the other side, Clojure shares a symbiotic relationship with the Java Virtual Machine, thus allowing prospective developers to avoid the costs of maintaining yet another infrastructure while leveraging existing libraries.
…The current concurrency model is too hard for developers to grok, and we need a better concurrent programming model that will help developers easily write and maintain concurrent programs… Scala takes a totally different approach to concurrency: the Actor model. An actor is a mathematical model of concurrent computation that encapsulates data, code, and its own thread of control and communicates asynchronously using immutable (no side effects) message-passing techniques…
- To mutate or not to mutate?
- Decorating with dynamic proxies
- State replication in the Web tier
- Are all stateful Web applications broken?
- Introduction to non-blocking algorithms
- Instrumenting applications with JMX