2

Suppose that a token machine can only issue one token at a time. The rule is that one token must be consumed before another one can be created.

class TokenMachine {
    private int tokenID;
    private boolean tokenExists = false;
    public synchronized void createToken(int coup){
      ...
    }
    public synchronized int consumeToken(){
      ...
    }
}

public synchronized void createToken(int coup) {
    while(tokenExists) { //can I change 'while' to 'if'?
        wait(); //in a try-catch block
    }
    this.tokenID = coup;
    tokenExists = true;
    notify();
}

public synchronized int consumeToken() {
    while(!tokenExists) { //can I change 'while' to 'if'?
        wait(); //in a try-catch block
    }
    tokenExists = false;
    notify();
    return tokenID;
}

My question is that can I change the 'while' expression in previous code to 'if' instead without vandalize the rule? Many thanks.

Thanks guys for answering my question, I checked a lot online, find the following info are helpful: A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops.

Apparently, the spurious wakeup is an issue (I doubt that it is a well known issue) that intermediate to expert developers know it can happen but it just has been clarified in JLS third edition which has been revised as part of JDK 5 development. The javadoc of wait method in JDK 5 has also been updated

3
  • You'd better use notifyAll() because you currently introduce the possibility that all threads will wait indefinitely if the 'wrong' thread is awakened by the notify(). Commented Oct 9, 2013 at 9:46
  • thanks Mark, I still don't understand, after call notify() what happen with the current thread that execute notify() method? Commented Oct 9, 2013 at 10:20
  • 1
    The notifying thread will continue to run and the notified thread(s) will be waiting to obtain the monitor (as if they are at the start of a synchronized block) until the notifying thread exits the synchronized block and releases the monitor. But I'd suggest to read a good book on concurrency in Java, it is too complex to explain in comments. Commented Oct 9, 2013 at 10:39

2 Answers 2

4

You need to use while to avoid waking up the thread in case of Spurious wake ups. In case of a spurious wake-up, a thread can be woken up without notify() being called. The while loop will recheck the condition and proceed only if it is a genuine notify call and not a spurious reactivation.

Sign up to request clarification or add additional context in comments.

2 Comments

thanks Hari, I still don't understand, after call notify() what happen with the current thread that execute notify() method?
It just carries on doing whatever it was doing.
0
class TokenMachine {
  ArrayBlockingQueue<Integer> q=new ArrayBlockingQueue<Integer>(1);

  public synchronized void createToken(int coup){
    q.put(coup);
  }

  public synchronized int consumeToken(){
    return q.get();
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.