java线程和互斥

时间:2015-04-18 12:47:22

标签: java multithreading concurrency locking monitor

我有以下类来代表银行系统:

作为监视器的类:BankAccount

public class BankAccount 
{
    private boolean isLocked = false;
    private int balance;
    private String name;
    private int nrWithdrawals;
    public  Transaction Transaction;

    public BankAccount()
    {
        this.balance = 300;
        this.name = "Bank Account";
    }

    public synchronized void  withdraw(Transaction tran)
    {
        while(!canWithdraw(tran))
        {
            try
            {  
                wait();
                System.out.println("Not enough money: ");                               
            }
            catch( InterruptedException e) {}
        }

        this.setBalance((this.getBalance() - tran.getBalance()));
        System.out.println("Remaining Balance is: " + this.getBalance());
    }


    public synchronized void depositMoney( )
    {
        while(this.getBalance() + 100 <= this.BankAccountLimit)
        {
            try
            {
                wait();
            }
            catch(InterruptedException e){}
        }

        this.setBalance(this.getBalance() + 100);
        System.out.println("Bank Account balance is: " + this.getBalance());
    }
}

一个名为(用户)

的类(线程)
public class User extends Thread
{   
    private final BankAccount account;
    private ThreadGroup threadGroup;
    private Transaction tran;
    private String bName;
    private String userName;

    public User(BankAccount acc, ThreadGroup group, String name)
    {
        super(group, name);
        this.account = acc
        this.userName = name;
        this.threadGroup = group;
    }

    public void run()
    {
        for(int i = 0; i< 3; i++)
        {
            Transaction transaction = new Transaction(70);
            account.withdraw(tran);

            System.out.println(this.getUserName() + " is using the bankaccount");
            try
            {  
                sleep(2000);     
            }
            catch(InterruptedException e){}
        } 
    }
}

一个名为Manager

的类(线程)
public class Manager extends Thread
{
    private final BankAccount account;
    private ThreadGroup threadGroup;
    private String managerName;

    public Manager(BankAccount acc, ThreadGroup tgroup, String name)
    {
        account = acc;
        threadGroup = tgroup;
        managerName = name;
    }

    public void run()
    {
        for(int i = 0; i < 3; i++)
        {
            account.depositMoney();
            try
            {
                sleep(100);
                System.out.println("trying....");
            }
        }
        catch(InterruptedException e){} 
    }  
}

和主要方法

public static void main(String[] args) 
{
    ThreadGroup users = new ThreadGroup("Users");
    ThreadGroup managers = new ThreadGroup("Managers");

    BankAccount account = new BankAccount();
    User user1 = new User(account, users, "User1");
    User user2 = new User(account, users, "User2");
    Manager manager = new Manager(account, managers, "Manager1");   
    user1.start();
    user2.start();
    manager.start();
}

我想要达到的目标是:

user1或user2开始提取资金(每次尝试多次)。假设user1首先启动。

如果没有足够的钱等到经理存款(试图存入三次或某些东西),一些钱,然后用户1恢复取款,然后用户2完成取款后。

我遇到的问题: 如何确保user1或user2是第一个运行的线程。 是否可以让线程等待,执行另一个并恢复正在等待的线程?(使用户1等待,执行管理器然后恢复用户1,然后执行剩下的用户?)

2 个答案:

答案 0 :(得分:2)

  

是否可以让线程等待,执行另一个并恢复正在等待的线程

是。您所指的是生产者 - 消费者问题的经典案例。

您可以使用synchronized关键字来使用显式同步。使用wait方法使线程释放它的锁,并使用notify方法通知线程锁现在可用。

您还可以使用ReenterantLock

答案 1 :(得分:1)

你在这里犯的错误很少。

  1. 您的余额不是线程安全的。两个线程可以在Withdraw和depositMoney方法中改变它。因此,您可以使用互斥锁ReenterantLock作为bot解释。
  2. 如果你的执行结束于wait(),或者Withdraw或depositMoney,那么就没有办法摆脱它。为避免这种情况,您可以在每次提款或存款后拨打notifyAll()。
  3. 以下是包含建议更改的示例代码

    public class BankAccount
        {
            private boolean isLocked = false;
            private int balance;
            private String name;
            private int nrWithdrawals;
            public  Transaction Transaction;
            private ReentrantLock lock = new ReentrantLock();
    
            public BankAccount()
            {
                this.balance = 300;
                this.name = "Bank Account";
            }
    
            public synchronized void Withdraw(Transaction tran)
            {
                lock.lock();
                while(!CanWithdraw(tran))
                {
                    try
                    {
                        lock.unlock();
                        System.out.println("Not enough money. Waiting for manager to deposit");
                        wait();
                        lock.lock();
    
                    }
                    catch( InterruptedException e) {}
                }
                this.setBalance((this.getBalance() - tran.getBalance()));
                notifyAll();
    
                System.out.println("Remaining Balance is: " + this.getBalance());
                lock.unlock();
            }
    
    
            public synchronized void depositMoney( )
            {
                lock.lock();
                while(this.getBalance() + 100 <= this.BankAccountLimit)
                {
                    try
                    {
                        lock.unlock();
                        wait();
                        lock.lock();
                    }
                    catch(InterruptedException e){}
                }
    
    
                this.setBalance(this.getBalance() + 100);
                notifyAll();
                System.out.println("Bank Account balance is: " + this.getBalance());
                lock.unlock();
            }
        }