简体   繁体   English

Java线程和互斥

[英]java threads and mutual exclusion

I have the following classes to represent a banking system: 我有以下课程来代表银行系统:

The class that is a monitor: BankAccount 监视者的类: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(thread) called: User 名为:用户的类(线程)

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(thread) called 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){} 
    }  
}

and a main method 和主要方法

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

What I would like to achieve would be something like this: 我想要实现的是这样的:

user1 or user2 start withdrawing money(each one try for a number of times). user1或user2开始提款(每次尝试多次)。 Lets say user1 starts first. 可以说user1首先启动。

If there is not enough money wait until the manager deposits(tries to deposit three times or something likethis) some money and afterwards user1 resumes withdrawing money then after he finishes user2 starts withdrawing money. 如果没有足够的钱,请等到经理存款(尝试存款3次或类似的东西),然后用户1恢复提款,然后他完成用户2之后便开始提款。

The issues I have: How do I make sure that either user1 or user2 is the first thread to run. 我遇到的问题:如何确保user1或user2是第一个运行的线程。 Is it posible make a thread wait, execute another and resume the one that is waiting ?(make user1 wait, execute manager then resume user1 and then execute the remaining user?) 是否可以让一个线程等待,执行另一个线程并恢复正在等待的线程?(使user1等待,执行管理器,然后恢复user1,然后执行其余的用户?)

Is it posible make a thread wait, execute another and resume the one that is waiting 是否可以让一个线程等待,执行另一个并恢复正在等待的线程

Yes. 是。 What you are referring to is a classic case of the producer-consumer problem. 您所指的是生产者-消费者问题的典型案例。

You can use explicit synchronization by using the synchronized keyword. 您可以通过使用synchronized关键字来使用显式同步。 Use the wait method to make a thread release it's locks and use the notify method to notify threads that the lock is now available. 使用wait方法使线程释放其锁,并使用notify方法通知线程该锁现在可用。

You can also use a ReenterantLock 您也可以使用ReenterantLock

There are few mistakes you have done here. 您在这里犯的错误很少。

  1. Your balance is not thread safe. 您的余额不是线程安全的。 Two threads can alter it within Withdraw and depositMoney methods. 两个线程可以在Withdraw和depositMoney方法中对其进行更改。 So you can use a mutex, ReenterantLock as bot explained. 因此,您可以按照bot的说明使用互斥锁ReenterantLock。
  2. If your execution ended up in wait(), either Withdraw or depositMoney then there is no way of getting out of it. 如果您的执行最终以wait(),Withdraw或depositMoney结尾,则无法摆脱它。 To avoid that you can call notifyAll() after each withdraw or deposit. 为了避免这种情况,您可以在每次提款或存款后调用notifyAll()。

Here is the sample code with the suggested alterations 这是带有建议更改的示例代码

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