3

I am new to multithreading. I am trying to write a program where I have two threads. One thread prints odd number and then gives up the monitor lock using wait() and similarly other thread prints the even number and gives up the lock after printing the number
I have got 4 classes

  1. Odd.java (print odd numbers between 1-100)
  2. Even.java(print even number between 1-100)
  3. SomeMaths.java( has got logic for printing odd and even numbers )
  4. OEApp.java (Main class that starts the threads)

Problem - My code works as expected most of the times i.e it print number 1 to 100 in order. Both the thread take turns. But I noticed that there is a bug.Sometimes the even thread gets scheduled first and gets below output

2    **********
1    ###############################

After that nothing gets printed, Looks like there is a deadlock situation. I am not able to figure out why. Please help me to understand this

public class SomeMaths {

    public synchronized void printOdd(){
        for( int i=1;i<=100;i++){
            if(i%2 !=0) {
                System.out.println(i + "       ###############################");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            notify();
        }
    }

    public synchronized void printEven(){
        for(int i=1;i<=100;i++){
            if(i%2 ==0){
                System.out.println(i +"    **********");
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            notify();
        }
    }
  }

public class Odd implements Runnable {

    SomeMaths sm;

    public Odd(SomeMaths sm){
        this.sm = sm;
    }
    @Override
    public void run(){
       sm.printOdd();
    }
}

public class Even extends Thread {

    SomeMaths sm;

    public Even(SomeMaths sm){
        this.sm = sm;
    }

    @Override
    public void run(){
        sm.printEven();
    }
}

public class OEApp {

    public static void main(String[] args) {

        SomeMaths sm = new SomeMaths();

        Thread odd = new Thread(new Odd(sm));
        Thread even = new Thread(new Even(sm));

        odd.start();
        even.start();

        try {
            odd.join();
            even.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
1
  • Curious: If Even extends Thread, why do you wrapper it with another thread using new Thread(new Even(sm))? Commented Jul 29, 2017 at 15:18

2 Answers 2

6

I believe it works this way:

  1. Even thread starts, 1 is odd so it calls notify (notifying no one), then 2 is even so it prints a message and waits

  2. Odd thread starts, 1 is odd so it prints a message and waits

  3. There's no one to call notify so both threads wait forever

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

1 Comment

I was about to ask what the solution is, but then realized question doesn't ask for solution, only explanation of why, so +1 from me.
-2

What is your purpose for using the synchronize keyword ?
It can only assure you that your function will not be running multiple times at the same time.

I assume that you want one thread to notify another ? Is that right ?
But what if the notify is called before the wait occurred ?

You know that you can use the debugger to see each thread, and thus know where each thread is stuck ?

Please keep in mind, once start is called, you can't know which thread will have cpu time.

Furthermore you are trying to synchronize two threads (by the use of the notify/wait mecanism), but there are other mecanisms that will be proved simpler (e.g. semaphore: each thread having it own semaphore, acquiring it own semaphore and releasing the other one semaphore; initialize each semaphore to 1 and it will go smoothly).

P.S. :

11 Comments

"What is your purpose for using the synchronize keyword ?" For one, it's required when using notify() and wait(), so that's a dumb question.
"Why use both runnable and thread interface ?" Because it is recommended to implement Runnable rather than extending Thread, which means you'll "use" both in the code. See “implements Runnable” vs. “extends Thread”.
Your comment about "Why use both runnable and thread interface ?" is a bit strange: I didn't advised to use either of them, but asked to the reason to use both of them.
And the comment answered that: Because it is recommended to implement Runnable and then give that as parameter to the Thread constructor, i.e. you will use both.
Agreed that Runnable is the best way to go but as I mentioned I am new to Threads, I was just playing around with both the approaches.
|

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.