Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most frequent concurrency issue you've encountered in Java? [closed]

People also ask

What are concurrency issues in Java?

Concurrency issues. Threads have their own call stack, but can also access shared data. Therefore you have two basic problems, visibility and access problems. A visibility problem occurs if thread A reads shared data which is later changed by thread B and thread A is unaware of this change.

What are concurrency issues?

When multiple transactions execute concurrently in an uncontrolled or unrestricted manner, then it might lead to several problems. These problems are commonly referred to as concurrency problems in a database environment.

How can concurrency issues be prevented?

The main way we can avoid such concurrency issues and build reliable code is to work with immutable objects. This is because their state cannot be modified by the interference of multiple threads. However, we can't always work with immutable objects.


My #1 most painful concurrency problem ever occurred when two different open source libraries did something like this:

private static final String LOCK = "LOCK";  // use matching strings 
                                            // in two different libraries

public doSomestuff() {
   synchronized(LOCK) {
       this.work();
   }
}

At first glance, this looks like a pretty trivial synchronization example. However; because Strings are interned in Java, the literal string "LOCK" turns out to be the same instance of java.lang.String (even though they are declared completely disparately from each other.) The result is obviously bad.


The most common concurrency problem I've seen, is not realizing that a field written by one thread is not guaranteed to be seen by a different thread. A common application of this:

class MyThread extends Thread {
  private boolean stop = false;

  public void run() {
    while(!stop) {
      doSomeWork();
    }
  }

  public void setStop() {
    this.stop = true;
  }
}

As long as stop is not volatile or setStop and run are not synchronized this is not guaranteed to work. This mistake is especially devilish as in 99.999% it won't matter in practice as the reader thread will eventually see the change - but we don't know how soon he saw it.


One classic problem is changing the object you're synchronizing on while synchronizing on it:

synchronized(foo) {
  foo = ...
}

Other concurrent threads are then synchronizing on a different object and this block does not provide the mutual exclusion you expect.


A common problem is using classes like Calendar and SimpleDateFormat from multiple threads (often by caching them in a static variable) without synchronization. These classes are not thread-safe so multi-threaded access will ultimately cause strange problems with inconsistent state.


Not properly synchronizing on objects returned by Collections.synchronizedXXX(), especially during iteration or multiple operations:

Map<String, String> map = Collections.synchronizedMap(new HashMap<String, String>());

...

if(!map.containsKey("foo"))
    map.put("foo", "bar");

That's wrong. Despite single operations being synchronized, state of map between invoking contains and put can be changed by another thread. It should be:

synchronized(map) {
    if(!map.containsKey("foo"))
        map.put("foo", "bar");
}

Or with a ConcurrentMap implementation:

map.putIfAbsent("foo", "bar");