2

I am new to using threads in java . I have a simple reader writer problem where that when a writer comes in on a thread, a reader will wait for the writer to complete.

However, when I run my program, I find that my thread doesn't get notified? Why is this?

My code is below:

public class ReaderWriter  {

Object o = new Object();
volatile boolean writing;
Thread readerThread = new Thread( "reader") {

    public void run() {

        while(true) {
            System.out.println("reader starts");
            if(writing) {
            synchronized (o) {
                try {
                    o.wait();
                    System.out.println("Awaked from wait");
                } catch (InterruptedException e) {                      
                    e.printStackTrace();
                }

            }
        }

            System.out.println( "reader thread working "+o.hashCode());

        }

    }
};
Thread writerThread = new Thread("writer" ) {
    public void run() {
        System.out.println( " writer thread");
        try {
            synchronized (o) {
                writing = true;
                System.out.println("writer is working ..  ");
                Thread.sleep(10000);                    
                writing = false;
                o.notify();
                System.out.println("reader is notified");
            }


        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

public static void main(String[] args) {
    ReaderWriter rw=new ReaderWriter();
    rw.readerThread.start();

    rw.writerThread.start();

}

}

Achyut
  • 377
  • 1
  • 3
  • 17

5 Answers5

4

Here the problem is with the synchronized (o) function.

The synchronized function makes the thread synchronized and there by it only execute only one thread at a time to the object o. Hence while the value of writing is true. It wont allow the 2nd tread readerThread to execute the due to the synchronized (o) in the readerThread

You are getting an Infinite loop because there is no terminate statement.
Look here to know when thread terminates

Look at this code to Know more about synchronized function

synchronized(object) {
   // statements to be synchronized
}

Here, object is a reference to the object being synchronized. A synchronized block ensures that a call to a method that is a member of object occurs only after the current thread has successfully entered object's monitor

.

Read this to check about the notify methods

The Object class in JavaSW has three final methods that allow threads to communicate about the locked status of a resource. These methods are wait(), notify(), and notifyAll(). A thread obtains a lock for a particular resource via a synchronized block with an instance of that resource. Suppose that a thread requires that another thread perform a certain action on the resource before it acts on the resource. That thread can synchronize on the resource and call the wait() method on resource. This says that the thread will wait until it has been notified that it can proceed to act.

The wait() method can take an optional timeout value as a parameter. If this value is used, it means that the thread will either wait until it's notified or it will continue to execute once the timeout value has passed.

If a thread is required to perform a task on a resource before another thread operates on the resource (and the other thread is waiting via the wait() method on the resource), the thread needs synchronize on the resource. It can perform its actions on the resource.

In order to notify the waiting thread once these actions have completed, the notify() method on the resource is called. This notifies the waiting thread that it can proceed to act. If multiple threads are waiting for the resource, there is no guarantee as to which thread will be given access to the resource. If it is desired for all waiting threads to be awoken, the notifyAll() method can be called on the resource.

Community
  • 1
  • 1
Dileep
  • 5,362
  • 3
  • 22
  • 38
  • @Achyut is the question answered ?? – Dileep Aug 26 '13 at 14:36
  • Thanks for reply .I got partial answer that How notify works ? but not the answer to my problem actually. syncronized(o) is actually not creating a problem because it is monitor that has been acquired and released by reader and writer. – Achyut Aug 26 '13 at 15:28
  • @Achyut syncronized(o) blocks the execution of the code within its bracket(Thats why u r not getting Awaked from wait message). and thus it goes back to the next thread.!! ie writerthread. and writer thread will again notify the reader but that wont execute because of the synchronized(o). This process will continue(Makes the infinite statement).. It will only terminate until you give a terminate statement.!! – Dileep Aug 26 '13 at 16:59
  • @achyut thats not the way it works, we help you to clear your doubts. You redo your code and varify wether it works. Once your problem is solved you can accept the answer which helped you to solve the issue.. !! Look into http://meta.stackoverflow.com/ for more details – Dileep Aug 26 '13 at 19:42
  • Yes I redo my code and asked on this forum only because I was not getting the expected output. for which no syncronized(o) is responsible but the culprit is writing = true and writing = false that I mentioned inside the syncronized block. – Achyut Aug 27 '13 at 09:00
  • @Achyut If you got more doubts in the new way, ask it again as a new Question..!! As far i know the issue here is resolved, we have explained why you are not getting the answer in the Question you asked..!! – Dileep Aug 27 '13 at 10:55
1

The problem is that writing is set to false prior notification.

Thread.sleep() alone does not wake up other waiting threads.

proskor
  • 1,382
  • 9
  • 21
  • thanks, I comment out the line writing = false but problem still persists – Achyut Aug 26 '13 at 14:14
  • I written writing=false after notify() but still the same. Thread.sleep is only for the writer thread to sleep for some time. – Achyut Aug 26 '13 at 14:20
1

The writer thread is always holding the lock on your monitor object while writing is set to true. This is why the synchronized block in your reader thread will never be entered while writing is set to true.

synchronized (o) { // Thread aquires lock on monitor o. writing is false.
    writing = true; // writing is true, lock still held.
    System.out.println("Writer is working...");
    Thread.sleep(1000); // Thread sleeps while holding lock.
    writing = false; // writing is changed back to false, lock still held.
    o.notify();
    System.out.println("Reader is notified");
} // Here lock is released, writing is false.

That is writing is set to false before aquiring the lock and it is false when releasing the lock. While the lock is held this synchronized block in the reader thread will not be entered:

while (true) {
    if (writing) {
        synchronized (o) { // Lock always held by writer when writing=true.
            try {
                o.wait();
                System.out.println("Awaked from wait");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
Felix Glas
  • 15,065
  • 7
  • 53
  • 82
  • Thanks nice description, but according to situation it is correct because before acquiring lock no writing is there so writing = false and after releasing lock writing must be set false because now the writing has been completed. – Achyut Aug 26 '13 at 15:23
  • yes when writing get false the monitor is released and so the statement "reader thread working "+o.hashCode()" should be printed – Achyut Aug 26 '13 at 15:25
0

thanks for your cooperation and valuable suggestions, I make a bit change in my code

public class ReaderWriter  {

Object o = new Object();
volatile boolean writing;
Thread readerThread = new Thread( "reader")  {

    public void run() {
        System.out.println("reader starts");

            synchronized (o) {
                    System.out.println("reader aquire the lock");
                    while(writing) {
                        try {                               
                            System.out.println("Reader goes to wait ....");
                            o.wait();                               
                            System.out.println("Awaked from wait");
                        } catch (InterruptedException e) {                      
                            e.printStackTrace();
                        }
                    }
                    while(!writing) {
                        //do something  
                        System.out.println("hiiiiiiii");
                    }
                    System.out.println("reader release the lock");  
                }
        }

    };

Thread writerThread = new Thread("writer" ) {
    public void run() {
        System.out.println( "writer starts");
        try {
            writing = true;
            synchronized (o) {                  
                System.out.println("writer aquire the lock");
                Thread.sleep(10000);        
                o.notify();                 
                System.out.println("reader is notified");
                System.out.println("writer release the lock");
            }
            writing = false;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

public static void main(String[] args) {
    ReaderWriter rw=new ReaderWriter();
    rw.readerThread.start();        
    rw.writerThread.start();

}

}

Now I found a thing very interesting that "Awaits from wait" only when reader acquire the lock first and after the correction I put writing = true and writing = false outside the syncronized block so that after acquiring the lock by the reader when writer comes it changes the writing flag and thus reader goes to wait and release the lock for writer, writer acquire the lock do Thread.sleep and notify the reader and hence release the lock for reader. Reader awakes and find that the writing flag is set to false by writer, so reader starts performing its operation.

Achyut
  • 377
  • 1
  • 3
  • 17
  • If you found any of the answers useful to solve your problem, you can reward the people that took the time to help you with an upvote/accept. [Accepting Answers: How does it work?](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work/5235#5235) – Felix Glas Aug 26 '13 at 17:38
0
There can be only two cases when writer thread first enters its critical section or when reader thread enters first since by no means you are stopping one to sleep for other to start first.

1) In first case when writer thread enters critical section first synchronized block locks the object o and after waking up from sleep you notify but you are not releasing lock explicitly till sync block ends which unlocks the object automatically .So even if notification is sent inside block reader thread wont be able to take the lock .So after syn block of your writer thread is over you reader thread would run uninterrupted assuming there is no interrupt from third thread .

2) In second case when  you reader thread is scheduled by scheduler to run first it will obtain a lock and on finding flag false it will enter infinite loop of printing hi on output console and its is infinite since you have take lock of object and entered infinite loop which makes writer thread wait indefinitely on reader thread  

Correcting your code as below for reader thread 

synchronized (o) {
    System.out.println("reader aquire the lock");
    if(writing) {
        try {                               
            System.out.println("Reader goes to wait ....");
                            System.out.println("Awaked from wait");
        } catch (InterruptedException e) {                      
            e.printStackTrace();
        }
    }
    else{
        //do something 
        o.notify(); 
        o.wait(); // in this case only reader release the lock would only be printed and if block wont be executed
    }
    System.out.printn("reader release the lock");  
}