Search code examples
javaconcurrencysummary

Use cases for Java concurrent utilities


I have read Java Concurrency in Practice and this is a great reference, but I would like to see a concise single page summary of the use cases of the java.util.concurrent package.

For instance:

  • Why use a concurrent collection over a synchronized collection?
  • When should the atomic classes be preferred over explicit locking?
  • When should Locks be used over synchronization?
  • What are the alternatives to wait() and notify(), notifyAll()?
  • When should a CompletionService be used?

What are the pros/cons and pitfalls to be aware of?


Solution

    • Why use a concurrent collection over a synchronized collection?

    Because a synchronized collection only protects data from corruption due to concurrent access. This does not mean that the synchronized collections are optimized for concurrent access. Far from it, in fact - a ConcurrentMap.putIfAbsent is a much better mechanism for a compareAndSet than locking the entire Map for reads.

    • When should the atomic classes be preferred over explicit locking?

    The AtomicInteger and AtomicLong classes should always be used (in my opinion) over locking by hand with a primitive because they are more concise. Consider:

    synchronized (lock) { 
        int old = counter;
        counter++;
        return old;
    }
    

    When compared with:

    int old = counter.getAndIncrement();
    

    I have to say though, that the classes suffer from their lack of waitability. For example, you often want some synchronized boolean where you wait on the boolean condition. These were available as WaitableBoolean in the old Doug Lea concurrency library but they were jettisoned in j.u.c, I'm not sure why.

    • When should Locks be used over synchronization?

    This is a more complicated question because usage of Locks carries some overhead. In fact, it's often said that there's no pint in using a ReadWriteLock in typical cases. One scenario where locks must be used is where the locking of a resource and its unlocking cannot be done in the same lexical scope. synchronized is powerless to help in cases such as these.

    • What are the alternatives to wait() and notify(), notifyAll()?

    await, signal and signalAll

    • When should a CompletionService be used?

    A completion service is useful in the case where the consumption of a result of a computation does not need to be accessed at the point the computation was submitted but where it is important that the completion of the computation (or its result, or success) be known by your program. This might be, for example, to monitor the proportion of failed tasks (which threw exceptions), or it may be for resource cleanup.