Vinay Pandey
Vinay Pandey

Reputation: 451

Java concurrent API Lock vs Synchronized on shared resources

I am trying to replace the simple Java thread code with its concurrent lock API. It might be the silly thing to ask it here, but i tried by my self and could not get any success. I have following classes. Hotel.java

public class Hotel implements Runnable {
    private Item item;

    Hotel(Item item) {
        this.item = item;
    }

    @Override
    public void run() {
        synchronized (item) {
            try {
                System.out.println("Ordered item = " + item.name);
                Cook cook = new Cook(item);
                Thread t = new Thread(cook);
                t.start();
                Thread.sleep(1000);
                item.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("total bill: " + item.price);
        }
    }

}

Cook.java

public class Cook implements Runnable {

    private Item item;

    Cook(Item item) {
        this.item = item;
    }

    @Override
    public void run() {
        synchronized (item) {

            try {
                System.out.println("Cooked item = " + item.name);
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            item.notify();
        }

    }
}

and Item.java

public class Item {

    String name;
    double price;

    public Item(String name, double price) {
        this.name = name;
        this.price = price;
    }

}

I have following Main.java class

public class Main {

    public static void main(String... args) {
        Item item = new Item("Burger", 100.00);
        Thread t = new Thread(new Hotel(item));
        t.start();

    }

}

When I run this Main class I get below output.

Ordered item = Burger
Cooked item = Burger
total bill: 100.0

I want to replace this code using concurrent Lock API of jdk1.5. I tried to use Lock instead of synchronized keyword, But I was not able to lock the item in two different classes(i.e. Hotel and Cook) using ReentrantLock. Since the Item is a shared resource between Hotel and Cook I should be able to lock it. I got IllegalMonitorStateException Exception.

Upvotes: 1

Views: 255

Answers (1)

Evan Jones
Evan Jones

Reputation: 886

What you are missing is that you also need to use

java.util.concurrent.locks.Condition

Essentially you can replace

java.lang.Object.wait(); and
java.lang.Object.notify();

with

java.util.concurrent.locks.Condition.await(); and
java.util.concurrent.locks.Condition.signal().

So if you change Item to

public class Item {
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    String name;
    ...
}

You can replace

synchronized (item) {
    ...
    item.wait();
}

with

item.lock.lock();
try {
    ...
    item.condition.await();
} finally {
     item.lock.unlock();
}

and replace:

synchronized (item) {
    ...
    item.notify();
}

with

item.lock.lock();
try {
    ...
    item.condition.signal();
} finally {
     item.lock.unlock();
}

Upvotes: 1

Related Questions