Rab
Rab

Reputation: 147

wait vs sleep in a synchronized method

I had a question for my exam in which I didn't receive full points due to something I don't quite understand.

The question is the following: Given the following program, apply changes that do not allow sum to be printed as a negative number.

public class Summer {

    private int sum;

    public void up() {
       sum++;
       System.out.println(sum);
    }

    public void down() {
       sum--;
       System.out.println(sum);
    }
}

the changes I made were the following:

public class Summer {

    private volatile int sum;

    public synchronized void up() {
       sum++;
       System.out.println(sum);
    }

    public synchronized void down() {
       while (sum <= 0) {
           try {
                Thread.sleep(100);
           } catch (InterruptedException e) { } 
       }
       sum--;
       System.out.println(sum);
    }
}

The answer I got is that I cannot use sleep in this program, and I have to use wait and I must use function notifyAll to awake the Thread.

My question is, why is what I wrote wrong? shouldn't volatile not allow sum to get cached and therefore I always get the updated version of sum since there is no possible way I get a "dirty copy" and therefore there is no way to print a negative sum?

Upvotes: 2

Views: 1767

Answers (2)

Harshad Sindhav
Harshad Sindhav

Reputation: 181

Sleep method puts thead on sleep method for a specific time while wait method holds threads execution untill someone awakes it. Hence your while loop will put your thread on endless loop. So use wait() instead of sleep(...) in down() and notify or notifyAll() in up method to awake down method when it increments and yes indees volatile variable gives each thread a fresh value always.

Upvotes: 2

Turing85
Turing85

Reputation: 20185

Your methods are synchronized. If down() is called and sum is <= 0, it will loop infinitely. Since synchronized methods synchronzie on this, no other thread can enter up() to release down() from its loop.

As for a solution, I think this should solve the problem:

public class Summer {

    private volatile int sum;

    public synchronized void up() {
        sum++;
        System.out.println(sum);
        this.notify(); // notify waiting threads that sum has changed
    }

    public synchronized void down() {
        while (sum <= 0) {
            try {
                this.wait(); // wait while sum <= 0. It is not sufficient to
                             // receive a notification and proceed since
                             // multiple threads may call down(). Also, the
                             // thread may wake up due to an interrupt, so
                             // it is advised putting wait() in a loop.
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        sum--;
        System.out.println(sum);
    }
}

Upvotes: 1

Related Questions