0

I have written a sample program to illustrate the working with pipe is thread. I have created 2 threads.

  1. Thread1 is sending "Hi this is thread1" and call wait() for thread 2 to complete.

  2. Thread2 is printing the message sent by thread1 and also will also append into a string buffer, then once the entire message is received, thread2 will print the contents of string buffer and will call notify. Now after calling wait() and notify both threads tend to be in deadlock

Strangely, thread2 prints the message one but does not print the contents of string buffer.

package com.tuto.MultiThreading;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class PipeExample {

    public static void main(String[] args) throws IOException, InterruptedException {
        final Object obj=new Object();
        final PipedOutputStream pipeoutstream=new PipedOutputStream ();
        final PipedInputStream pipeinputstream=new PipedInputStream(pipeoutstream);

        Thread thread1= new Thread(new Runnable()
        {

            public void run() {
                try {
                    pipeoutstream.write("Hello I am thread1".getBytes());
                    synchronized (obj) 
                    {

                        obj.wait(); 
                    }

                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                finally
                {
                    try {
                        pipeoutstream.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }   
                }

            }

        });


          Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    try {

                        int data = pipeinputstream.read();
                        StringBuffer sb=new StringBuffer();
                        while(data != -1){
                            System.out.print((char) data);
                            sb.append((char)data);
                            data = pipeinputstream.read();
                        }
                        System.out.println();
                        System.out.println(sb.toString());
                        synchronized (obj) {

                            obj.notify();
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    finally
                    {
                        try {
                            pipeinputstream.close();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }   
                    }
                }
            });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.exit(1);
    }
}

OUTPUT:: Hello I am thread1

Updated Resolution:

package com.tuto.MultiThreading;

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class PipeExample {

    public static void main(String[] args) throws IOException, InterruptedException {
        final Object obj=new Object();
        final PipedOutputStream pipeoutstream=new PipedOutputStream ();
        final PipedInputStream pipeinputstream=new PipedInputStream(pipeoutstream);

        Thread thread1= new Thread(new Runnable()
        {

            public void run() {
                try {
                    pipeoutstream.write("Hello I am thread1".getBytes());


                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                finally
                {
                    try {
                        pipeoutstream.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }   
                    synchronized (obj) 
                    {

                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }   
                    }
                }

            }

        });


          Thread thread2 = new Thread(new Runnable() {
                public void run() {
                    try {

                        int data = pipeinputstream.read();
                        StringBuffer sb=new StringBuffer();
                        while(data != -1){
                            System.out.print((char) data);
                            sb.append((char)data);
                            data = pipeinputstream.read();
                        }
                        System.out.println();
                        System.out.println(sb.toString());
                        synchronized (obj) {

                            obj.notify();
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    finally
                    {
                        try {
                            pipeinputstream.close();
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }   
                    }
                }
            });

        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.exit(1);
    }
}

Now i am a bit more confused. I just moved wait() from try catch to finally. How did it affect the blocking of Pipestream?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Maclean Pinto
  • 1,075
  • 2
  • 17
  • 39

1 Answers1

2

The problem is that

data = pipeinputstream.read();

in thread 2 is a blocking call. From the javadoc of PipedInputStream#read()

This method blocks until input data is available, the end of the stream is detected, or an exception is thrown.

Thread 2 keeps waiting until one of those things happen. Since none of them will ever happen, the thread will not be able to notify the other.

This is not deadlock.

Note that even if that call unblocked and returned -1, thread 2 could still execute its notify before your thread 1 called wait. In which case, thread 1 would be a in a constant waiting state and your program would not terminate.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Hi, I moved the wait from try to finally and it works. So why was wait effecting pipestream? – Maclean Pinto Feb 20 '15 at 05:15
  • if that call unblocked and returned -1, thread 2 could still execute its notify before your thread 1 called wait. In which case, thread 1 would be a in a constant waiting state and your program would not terminate. This is false because it would come out of the while and print string buffer contents – Maclean Pinto Feb 20 '15 at 05:17
  • 1
    @MacleanPinto The `wait` prevented thread 1 from closing the stream and unblocking the thread 2's call to `read`. – Sotirios Delimanolis Feb 20 '15 at 05:21
  • @MacleanPinto You cannot control the thread scheduler. Let's take your new solution. If thread calls `close` and there's a context switch, thread 2 will now be able to execute. Say it executes everything including the `notify` call before there's another context switch, thread 2 will resume with a call to `wait`. There will then be nothing left to `notify` it. – Sotirios Delimanolis Feb 20 '15 at 05:23