Odd even number printing using thread

13,157

Solution 1

You're waiting and notifying different objects (monitors).

The idea is that you can call obj.wait() to wait for someone to do obj.notify(), while you're doing objA.wait() and objB.notify().

Change your printOdd method to something like

private void printOdd(int i) {
    synchronized (lock) {                        // <-------
        while (!oddTurn) {
            try {
                lock.wait();                     // <-------
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + i);
        oddTurn = false;
        lock.notifyAll();                        // <-------
    }
}

and the printEven method similarly.

Then provide the NumberPrinter with a lock object:

Object lock = new Object();
Thread odd = new Thread(new NumberPrinter("odd", lock));
Thread even = new Thread(new NumberPrinter("even", lock));

Output:

odd1
even2
odd3
even4
odd5
even6
odd7
even8
odd9

Solution 2

There are a lot of bugs in the code.

First of all, the synchronized statements have no effect whatsoever. You create two thread instances, and each calls only its own methods. synchronized is only useful if another thread can call a method.

Then notifyAll() has no effect for the same reasons. odd.notifyAll() doesn't reach even hanging in the wait().

So what you need is another object which contains the state and which both threads can see and use. Use synchronized, wait() and notifyAll() on that third instance.

Solution 3

The same can be solved using Lock interface:

NaturalOrder.java

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class NaturalOrder {

    public int currentNumber = 1;
    public boolean evenOdd = false;

    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public static void main(String[] args) {
        NaturalOrder naturalOrder = new NaturalOrder();
        Thread t1 = new Thread(new OddNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        Thread t2 = new Thread(new EvenNumberLock(naturalOrder, naturalOrder.lock, naturalOrder.condition));
        t1.start();
        t2.start();
    }
}

OddNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class OddNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public OddNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != false) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (naturalOrder.currentNumber % 2 != 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = true;

            condition.signalAll();
        }
        lock.unlock();
    }
}

EvenNumberLock.java

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class EvenNumberLock implements Runnable {

    NaturalOrder naturalOrder;
    Lock lock;
    Condition condition;

    public EvenNumberLock(NaturalOrder naturalOrder, Lock lock, Condition condition) {
        this.naturalOrder = naturalOrder;
        this.lock = lock;
        this.condition = condition;
    }

    @Override
    public void run() {
        lock.lock();
        while (naturalOrder.currentNumber < 20) {
            while (naturalOrder.evenOdd != true) {
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            try {
                Thread.sleep(ThreadLocalRandom.current().nextInt(1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (naturalOrder.currentNumber % 2 == 0) {
                System.out.println(naturalOrder.currentNumber);
            }
            naturalOrder.currentNumber++;
            naturalOrder.evenOdd = false;
            condition.signalAll();
        }
        lock.unlock();
    }
}

Solution 4

I did this way

public class OddEven{
        public static void main(String[] args){
            Print o=new Print();
            Thread even=new Thread(new MyRunnable(2,o));
            Thread odd=new Thread(new MyRunnable(1,o));
            even.start();
            odd.start();
        }
}
class MyRunnable implements Runnable{
        int start;
        Print ob;
        MyRunnable(int s,Print o){
            start=s;
            ob=o;
        }
        public void run(){
            for(int i=start;i<=20;i+=2)
                ob.display(i);
        }   
}
class Print{
        int rem=0;
        synchronized void display(int n){
            while(n%2==rem)
                try{
                    wait();
                }
                catch(Exception e){System.out.println("Display interrupted");}
            System.out.print(n+" ");
            rem=n%2;
            notify();
        }           
}

Solution 5

I think the problem might be that printOdd and printEven synchronize on different lock (the Thread's object instance locks). Therefor you have not guaranteed that the change on the static variable oddTurn will be visible in the other thread. Try to make the oddTurn volatile for the start.

Share:
13,157
Sourabh
Author by

Sourabh

Developer

Updated on August 05, 2022

Comments

  • Sourabh
    Sourabh over 1 year

    Odd even number printing using thread.Create one thread class, two instance of the thread. One will print the odd number and the other will print the even number.

    I did the following coding. But it comes to dead lock state. Can some one please explain what might be the reason for that?

    public class NumberPrinter implements Runnable{
    private String type;
    private static boolean oddTurn=true;
    
    
    public NumberPrinter(String type){
        this.type=type;
    }
    public void run() {
        int i=type.equals("odd")?1:2;
        while(i<10){
            if(type.equals("odd"))
                printOdd(i);
            if(type.equals("even"))
                printEven(i);
            i=i+2;
        }
    
    }
    
    private synchronized void printOdd(int i){
        while(!oddTurn){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(type + i);
        oddTurn=false;
        notifyAll();
    }
    
    private synchronized  void printEven(int i){
        while(oddTurn){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace(); 
            }
        }
        System.out.println(type + i);
        oddTurn=true;
        notifyAll();
    
    }
    
    public static void main(String[] s){
        Thread odd=new Thread(new NumberPrinter("odd"));
        Thread even=new Thread(new NumberPrinter("even"));
        odd.start();
        even.start();
    
    }
    }
    

    Out Put: odd1 even2


    then comes to deadlock!!!!!!

    Thanks for your help.

  • Sourabh
    Sourabh almost 13 years
    Thanks for your response. Even after using volatile also getting the same result. It is going to deadlock.
  • Vladimir Ivanov
    Vladimir Ivanov almost 13 years
    See other answers, I have missed the fact, that yo uhave two objects, so no real synchronization is performed.
  • aioobe
    aioobe almost 13 years
    volatile doesn't matter. Both threads access different variables.
  • aioobe
    aioobe almost 13 years
    You don't need to let the common object to contain any state in this case. See my answer.
  • Aaron Digulla
    Aaron Digulla almost 13 years
    That's true but it makes it more simple to see which state is shared between the two threads. Multithreaded programming is already complex enough without adding more complexity :-)
  • aioobe
    aioobe almost 13 years
    Agreed. Tasks like these should, unless they are part of some homework, also be coded using the java.util.concurrent package :)