开发者

java multithreading problem

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=nextBloc开发者_Go百科k;
                    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
            }
        //}
    }
}


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.


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:"


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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜