繁体   English   中英

Java线程和互斥

[英]java threads and mutual exclusion

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

监视者的类: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){}
        } 
    }
}

称为管理器的类(线程)

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首先启动。

如果没有足够的钱,请等到经理存款(尝试存款3次或类似的东西),然后用户1恢复提款,然后他完成用户2之后便开始提款。

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

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

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

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

您也可以使用ReenterantLock

您在这里犯的错误很少。

  1. 您的余额不是线程安全的。 两个线程可以在Withdraw和depositMoney方法中对其进行更改。 因此,您可以按照bot的说明使用互斥锁ReenterantLock。
  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();
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM