Question

first of all I am very new here, so I hope I will do all things right during questioning.

The problem:

I have a class Store with an attribute int size;

In this class are two methods to manipulate the size attribute.

`public synchronized void leave(){
   this.size++;
}`

`public synchronized void enter(){
   while(this.size==0){ }
   this.size--;
}`

If I initialize the Store Object with size=2;for example and 4 other objects (the 4 threads) alternately try to leave() or enter()the Store object I will get an endless loop. I thought if I write synchronized methods, the leave method could also be called by a thread although a other thread will hang in the endless loop.

I hope my question is understandable. Thank you very much for your help.

Was it helpful?

Solution

first of all I am very new here, so I hope I will do all things right during questioning.

Your question is asked well so you got at least that right :)

4 other objects (the 4 threads) alternately try to leave() or enter()the Store object I will get an endless loop

When one thread enters the synchronized block, you are declaring that no other threads can enter a synchronized region of the same object until the thread has left the initial synchronized block. What you have is a thread invoking enter and spinning until size is 0. For that to happen, size needs to be incremented, which cannot happen because another thread cannot invoke leave (while the other thread is spinning for ever).

Solution

Instead of busy spinning ( while(<some condition>){ } ), have the thread wait on the monitor. This will give up the lock so another thread can enter. And after leaveing, notify any waiting threads.

public synchronized void leave(){
   this.size++;
   this.notify();
}

public synchronized void enter(){
   while(this.size==0){ 
       this.wait();
   }
   this.size--;
}

OTHER TIPS

On the same note as other solution you can consider the folowing solution too. It is better in 2 things 1. instead of synchronizing on method reduce lock scope 2. much clear approach thank using the wait-notify solution

class ConditionExample {
    final Lock lock = new ReentrantLock();
    final Condition resourceAvailable = lock.newCondition();

    private int size = 2;

    public void leave() throws InterruptedException {
        lock.lock();
        try {
            size++;
            //signal other waiting threads
            resourceAvailable.signal();
        } finally {
            lock.unlock();
        }
    }

    public void enter() throws InterruptedException {
        lock.lock();
        try {
            //Check condition
            while (size == 0)
                resourceAvailable.await();
            size--;
        } finally {
            lock.unlock();
        }
    }
}

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top