Search code examples
javamultithreadingrace-condition

Can Synchronized Methods Have Race Conditions? [Example]


I am learning about synchronized methods as a means of preventing race conditions and unwanted behavior in Java. I was presented with the following example, and told the race condition is quite subtle:

public class Messages {
  private String message = null;
  private int count = 2;

  // invariant 0 <= count && count <= 2

  public synchronized void put(String message) {
    while( count < 2 )
      this.wait();
    this.message = message;
    this.count = 0; 
    this.notifyAll(); 
  }

  public synchronized String getMessage() {
    while( this.count == 2 )
      this.wait();
    String result = this.message;
    this.count += 1;
    this.notifyAll();
    return result; 
  }
}

Subtle or not, I think I have a fundamental misunderstanding of what synchronized methods do. I was under the impression they restrict access to threads through use of a lock token (or similar), and thus can never race. How, then, does this example have a race condition, if its methods are synchronized? Can anyone help clarify?


Solution

  • Think about ways that count could become > 2...

    That code has a bad smell, too. What is count supposed to be counting? Why does get increment it and put reset it? Why the unnecessary use of 'this'? If I saw code like that in a project, I would look at it very carefully...