java线程和互斥

java threads and mutual exclusion

我有以下 classes 来表示银行系统:

为班长的class: 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());
    }
}

A class(线程)调用:用户

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){}
        } 
    }
}

A class(线程)称为经理

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 是 运行 的第一个线程。 是否可以让一个线程等待,执行另一个线程并恢复正在等待的线程?(让 user1 等待,执行管理器然后恢复 user1,然后执行剩余的用户?)

Is it posible make a thread wait, execute another and resume the one that is waiting

是的。你说的是生产者消费者问题的经典案例。

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

您也可以使用 ReenterantLock

你在这里犯的错误很少。

  1. 您的余额不是线程安全的。两个线程可以在 Withdraw 和 depositMoney 方法中更改它。因此,您可以使用互斥体 ReenterantLock,如 bot 所述。
  2. 如果您的执行在 wait()、Withdraw 或 depositMoney 中结束,则无法退出。为避免这种情况,您可以在每次取款或存款后调用 notifyAll()。

这是包含建议更改的示例代码

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();
        }
    }