Skip to main content

A Dozen Concurrency Pitfalls

Posted by cayhorstmann on May 4, 2011 at 8:52 PM PDT

I needed some filler material for my lectures on concurrency. I googled around for Java concurrency pitfalls and came up with a nice mixture of golden oldies and new ones (at least new to me). I cleaned them up and translated them into Scala because that's what we use in the course. Here they are, for your puzzling pleasure.

style="float: right; margin-left: 1em;" width="211" height="239" />

Rules of the game:


<p>You gonna teach actors again, I'm hoping? That was a lot ...

You gonna teach actors again, I'm hoping? That was a lot of fun, and certainly less prone to burning your laptop up :)

<p>You forget this one which is fairly ...

You forget this one which is fairly common:

class Stack(val maxSize: Int) {
  private val array = new ArrayDeque[Int]

  def put(value: Int) {
    array.synchronized {
      while(array.size == maxSize) {

<p>&nbsp;1. stop is not volatile so jvm spec cant guarantee ...

1. stop is not volatile so jvm spec cant guarantee the changed stop value to be visible among threads
2. stop.set(false) invocation should be stop.set(true)
3. called run() - wont spawn new thread, should call start() - this spawns new thread
4. val keys = items.keySet().toArray has no sense if it is not run in keys.synchronized block - other threads may change items and toArray will throw ConcurrentModificationException
5. "LOCK" String is pointing to instance in JVM`s internal strings cache (somewhere in String class) - this synchronized method may cause much "wider" synchronization than it seems (global lock on all non-new "Lock" Strings)
6. locking on "always new objects" is not wise :)
7. reallocate method creates new instance of values variable. it means that synchronized monitors flies away and other threads are able to step inside values.synchronized {} block despite fact that the first thread didnt leave this block
8. this Scala snippet is unreadable to me, I know only plain old Java :)
9. new PrintWriter(fileName) called outside of try {} block - costructor used in snippet throws FileNotFoundException, so it can never release acquired lock
10. potentially blocking EventDispatchThread - not wise :)
11. dont see anything unusual to me, new ChangeEvent(this) may seem a little fishy but ReentrantLock is always open for thread, which owns the lock
12. SimpleDateFormat object is shared but it`s not thread safe, it should be cloned or new instance should be spawned before format
13. synchronizes on this.array but waits on this = IllegalMonitorStateException
Btw. Scalas generics in [] looks so misleading... why did they change that? o_O

Some additional answers: 8. The problem is the do { ... } ...

Some additional answers:

8. The problem is the do { ... } while () loop as it calls cond.await() at least once, even if size > 0.
11. It is not wise to invoke stateChanged on the listener while holding the lock, as you do not know how long this method takes. Moreover, if the listener removes itself from the model (or adds a new listner) then you get an exception (in Java you would get a ConcurrentModificationException)