1

Below is part of the code. I am confused why "notify 1" can not really wake another function that is waiting.

It seams have something to do with: When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

Why the result is not: wait, notify1, wait finish, notify2, . . .

instead it is: wait, notify1, notify2, notify2, . . . notify2, notify 2, notify 3, wait finish, skip wait, skip wait, skip wait, . . .

code { . . .

    MultiThreadContent m;

    void divideToParts(File testFile,FileInputStream fileInputStream, Object hashMachine) throws IOException, InterruptedException{

        .
        .
        .
        //run from here
        m = new MultiThreadContent(fileInputStream,(int)temp23,(int) (testFile.length()%temp23), numberOfParts, hashMachine);
        new Thread(new Read()).start();
        m.update();
    }

    class Read implements Runnable{
        @Override
        public void run() {
            try {
                m.read();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    class MultiThreadContent{

        .
        .
        .


        boolean preNotReady=true;
        boolean updateNotFinished;

        //read{
            public synchronized void read() throws InterruptedException{
                //initial{
                    readNextBlock();
                    preBlock=nextBlock;
                    read_notify();
                    System.out.println("notify 1");//d
                    if(finishedRead!=true)
                    {
                        readNextBlock();
                        read_wait();
                    }
                    else
                        return;
                //}
                while(finishedRead!=true){
                    preBlock=nextBlock;
                    read_notify();
                    System.out.println("notify 2");//d
                    readNextBlock();
                    read_wait();
                }
                //closing{
                    preBlock=nextBlock;
                    read_notify();
                    System.out.println("notify 3");//d
                //}
            }
            void read_notify(){
                preNotReady=false;
                notifyAll();
            }
            void read_wait() throws InterruptedException{
                if(updateNotFinished==true)
                {
                    wait();
                    System.out.println("wait for update");//d
                }
                preNotReady=true;
            }
        //}


        //update{
            public synchronized void update() throws InterruptedException{
                for (int i = 0; i < totalParts; i++) {
                    update_wait();
                    divideToParts_update(hashMachine, preBlock);
                    update_notify();
                }
            }
            void update_notify(){
                updateNotFinished=false;
                notifyAll();
            }
            void update_wait() throws InterruptedException{
                if(preNotReady){
                    System.out.println("wait");//d
                    wait();
                    System.out.println("wait finish");//d
                }
                updateNotFinished=true;
                System.out.println("skip wait");//d
            }
        //}
    }
}
2
  • 1
    finishedRead is not defined? Is this all of the code? Commented Apr 11, 2011 at 13:58
  • it is part of the code. I am confused why notifyAll can not really wake another function that is waiting at "notify 1". Commented Apr 11, 2011 at 14:03

3 Answers 3

1

The reason is because you have not left the synchronized block. The read_wait method never enters the if block because updateNotFinished is default initialized to false. Since read_wait never enters the if block you will continue to loop on finishedRead!=true. Until that method and synchronized block is exited you will never give up a hold of the monitor.

Once you complete then the lock is available and the other thread is awaken correctly.

To test what I am talking about, try setting updateNotFinished = true on initialization.

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

8 Comments

@John V. But I have updateNotFinished=true; in the update_wait(). However, due to the nofifyAll in read() doesn't not wake the wait() in update_wait(), the updateNotFinished=true; command doesn't not run until late..
@micahli123 The issue you are seeing is simply because the thread in read() never exits. A synchronized method ensures mutual exclusion, and notifyAll only will wake up threads when no other threads are in the synchronized block. Since you never leave the synchronized block any waiting threads will never be awaken until you exit said block. Basically, updateNotFinished = true in update_wait never gets called until the first thread completes.
@John V. After I tried your test, the notify1 do work: wait notify 1 wait finish skip wait skip wait skip wait skip wait skip wait, but i still don't know why notify1 doesn't work in my example..
@John V I have got your point. I don't know they are mutually exclusive... But do you have any suggestion to make them "not mutually exclusive"... I think I have to read some material about interrupt..
Yea it would be a good lesson to learn. Multithreading is difficult to get right. You had the right idea, you just had a wrong understanding of what is expected to happen.
|
0

I don't know if this is the problem you are encountering, but it will definitely become a problem. All calls to .wait() have to be enclosed in a while loop. Calls to wait() can just randomly wake up.

Per the documentation: "As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:"

1 Comment

Thanks for your teaching! I believe it can be the problem. But even I have corrected this the problem still exists.
0

I find that the newer concurrency libraries are much easier to use than wait()/notify() These libraries were added for a reason and they are well worth learning. Here is an example of how your code could be simplified.

String filename = ...
ExecutorService es = Executors.newFixedThreadPool(5);
FileInputStream fis = new FileInputStream(filename);

while (true) {
    final byte[] buffer = new byte[8 * 1024];
    final int len = fis.read(buffer);
    if (len < 0) break;
    es.submit(new Runnable() {
        public void run() {
            process(buffer, len);
        }
    });
}
fis.close();
es.shutdown();
es.awaitTermination(60, TimeUnit.MINUTES);

1 Comment

It is amazing. I will try it. Looks like the same. It seems more flexible.

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.