Java and Synchronisation Bugs

Here’s a Java class that can safely be used by multiple threads:


public class Threshold {

private long threshold = 0;

public synchronized long getThreshold() {
return threshold;
}

public synchronized void setThreshold(long threshold) {
this.threshold = threshold;
}
}

Each public method is marked as synchronized.

What if a few months later someone adds another method:


public class Threshold {

private long threshold = 0;

public synchronized long getThreshold() {
return threshold;
}

public synchronized void setThreshold(long threshold) {
this.threshold = threshold;
}

public boolean isZero() {
return threshold == 0;
}
}

Suddenly it is not thread-safe. The person who added the new method didn’t realise that all accesses to threshold had to be protected. Now the isZero() method might be checking the value of threshold midway between the setThreshold() method changing it. The results are unpredictable.

This is a bad problem. Here’s why:

  • the code compiles.
  • the unit tests still pass.
  • the app testers will not detect the bug
  • almost of the time the code will still work. But sporadically, unpredictably, unfathomably, the code will fail.

I found – and fixed – such a problem in Poker Copilot a few days ago.

Currently the only way I know of to detect such problems is careful code reviewing. In a one-person company, careful code reviewing isn’t possible. In most other software teams it is possible but doesn’t happen.

So what can be done about it? I don’t know. It would be nice if a class could be marked as synchronized. Then all methods would automatically be synchronized. It would also be nice if there existed an annotation to indicate the same thing. Our static analysis tools would be then able to ensure that all methods were indeed synchronized.

This is one of many examples that demonstrate how brittle thread-safe code is.