0

I want to replace await(),signalAll() with wait(),notifyAll() (java's default monitor) and my code listed below, the problem is that once thread get into waiting state. it never be notified again.. Thanks for your help.

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class AccountThreadCommunicationDefault {
    private static Account account = new Account();
    private static Random random = new Random();
    public static void main(String... args) {
        ExecutorService es = Executors.newFixedThreadPool(2);
        es.execute(new WithdrawTask());
        es.execute(new DepositTask());
        es.shutdown();
    }

    private static class WithdrawTask implements Runnable {
        public void run() {
            while (true) {
                account.withdraw(random.nextInt(600));
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }
    }

    private static class DepositTask implements Runnable {
        public void run() {
            while (true) {
                account.deposit(random.nextInt(500));
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    private static class Account {
        private Integer balance = 500;
        private static Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        // private Object object = new Object();

        // public synchronized void deposit(int count) {
        public void deposit(int count) {
            try {
                lock.lock();
                System.out.print("当前账户余额:" + balance);
                balance += count;
                System.out.println(" 存款:" + count + " 账户余额(deposit): "
                        + getBalance());
                // synchronized (object) {
                // object.notifyAll();
                // }
                synchronized (this) {
                    this.notify();
                }
            } catch (IllegalMonitorStateException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }

        public void withdraw(int count) {
            try {
                lock.lock();
                while (balance < count) {

                    System.out.println("余额不足:" + getBalance() + " 等待存款..");
                    // synchronized (object) {
                    // object.wait();
                    // }
                    synchronized (this) {
                        this.wait();
                    }

                    System.out.print("当前账户余额:" + balance);
                    balance -= count;
                    System.out.println(" 取现:" + count + " 账户余额(withdraw): "
                            + getBalance());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }

        public int getBalance() {
            return this.balance;
        }
    }

}

1 Answers1

1

You have a deadlock. The Withdraw task is waiting on the Account object's monitor, while holding the ReentrantLock locked. The Deposit task can not notify() the Account object monitor because it can't lock the ReentrantLock.

You need to wait() and notify() the same object that you are using as a mutex. Doesn't matter whether it's the ReentrantLock or the Account object's monitor. But it won't work the way you wrote it with two different locks.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57