Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/347.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java同步银行模拟器_Java_Multithreading_Synchronization_Thread Synchronization - Fatal编程技术网

Java同步银行模拟器

Java同步银行模拟器,java,multithreading,synchronization,thread-synchronization,Java,Multithreading,Synchronization,Thread Synchronization,我有一个方法transfer(),它从一个帐户取款并存入另一个帐户。有10个帐户,每个帐户都使用自己的线程运行。我还有另一个方法test(),它对每个账户的总额进行汇总,以确保银行没有赔钱或赚钱。为了得到准确的总数,我创建了一个布尔标志来指示测试是否正在进行。如果是,我需要以某种方式暂停传输,直到测试完成。我尝试使用一个同步块来实现这一点,告诉线程等待某个条件,并在该条件不再为真时释放。由于某种原因,我有困难。我的传输方法如下所示: public class Bank { public

我有一个方法transfer(),它从一个帐户取款并存入另一个帐户。有10个帐户,每个帐户都使用自己的线程运行。我还有另一个方法test(),它对每个账户的总额进行汇总,以确保银行没有赔钱或赚钱。为了得到准确的总数,我创建了一个布尔标志来指示测试是否正在进行。如果是,我需要以某种方式暂停传输,直到测试完成。我尝试使用一个同步块来实现这一点,告诉线程等待某个条件,并在该条件不再为真时释放。由于某种原因,我有困难。我的传输方法如下所示:

public class Bank {

    public static final int NTEST = 10;
    private Account[] accounts;
    private long ntransacts = 0;
    private int initialBalance;
    private int numAccounts;
    private boolean open;
    private int transactsInProgress;
    private boolean testing=false;

    public Bank(int numAccounts, int initialBalance) {
        open = true;
        this.initialBalance = initialBalance;
        this.numAccounts = numAccounts;
        accounts = new Account[numAccounts];
        for (int i = 0; i < accounts.length; i++) {
            accounts[i] = new Account(this, i, initialBalance);
        }
        ntransacts = 0;
        transactsInProgress = 0;
    }
    public synchronized void incrementTransacts(){
        transactsInProgress++;
    }
    public synchronized void decrementTransacts(){
        transactsInProgress--;
    }

    public void transfer(int from, int to, int amount) throws InterruptedException {

    accounts[from].waitForAvailableFunds(amount);
    synchronized(this){
        while(testing){
            System.out.println("Cannot transfer while testing...");
            this.wait();
        }
    }
        if (!open) return;
        if (accounts[from].withdraw(amount)) {
            incrementTransacts(); //synchronzied method increments transactsInProgress
            accounts[to].deposit(amount);
            decrementTransacts(); //synchronized method
        }
        if (shouldTest()) test();

    synchronized(this){
        this.notifyAll();
    }    
    }

    public synchronized void test() throws InterruptedException {
        int sum = 0;

        testing=true;
        while(transactsInProgress!=0){
                System.out.println("Cannot test while transactions are in progres... \nWaiting...");
            wait();
        }

        for (int i = 0; i < accounts.length; i++) {
            System.out.printf("%s %s%n", 
                    Thread.currentThread().toString(),accounts[i].toString());
            sum += accounts[i].getBalance();
        }
        System.out.println(Thread.currentThread().toString() + 
                " Sum: " + sum);
        if (sum != numAccounts * initialBalance) {
            System.out.println(Thread.currentThread().toString() + 
                    " Money was gained or lost");
            System.exit(1);
        } else {
            System.out.println(Thread.currentThread().toString() + 
                    " The bank is in balance");
        }
        testing=false;
        notifyAll();
    }
       public int size() {
        return accounts.length;
    }

    public synchronized boolean isOpen() {return open;}

    public void closeBank() {
        synchronized (this) {
            open = false;
        }
        for (Account account : accounts) {
            synchronized(account) {
                account.notifyAll();
            }
        }
    }

    public synchronized boolean shouldTest() {
        return ++ntransacts % NTEST == 0;
    }
}
公共类银行{
公共静态最终综合测试=10;
私人账户[]账户;
私有长ntransacts=0;
私人资产负债表;
私人整数;
私有布尔开放;
私人投资进展;
私有布尔测试=假;
公共银行(整数,整数初始余额){
开放=真实;
this.initialBalance=initialBalance;
this.numAccounts=numAccounts;
账户=新账户[numAccounts];
对于(int i=0;i
我已经有一段时间没有用Java编写代码了,而且我对线程和并发性还不熟悉,所以我不确定到底哪里出了问题。当我运行程序时,银行金额不正确。每个帐户有10000英镑,所以每次的金额应该是100000英镑。有什么想法吗

编辑:线程类和主线程:

class TransferThread extends Thread {

    public TransferThread(Bank b, int from, int max) {
        bank = b;
        fromAccount = from;
        maxAmount = max;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            int toAccount = (int) (bank.size() * Math.random());
            int amount = (int) (maxAmount * Math.random());
            bank.transfer(fromAccount, toAccount, amount);
        }
        bank.closeBank();
    }
    private Bank bank;
    private int fromAccount;
    private int maxAmount;
}
类TransferThread扩展线程{
公共转帐线程(银行b,整数从,整数最大){
bank=b;
fromAccount=from;
最大金额=最大金额;
}
@凌驾
公开募捐{
对于(int i=0;i<10000;i++){
int-toAccount=(int)(bank.size()*Math.random());
int amount=(int)(maxaount*Math.random());
银行转账(从账户、到账户、金额);
}
bank.closeBank();
}
私人银行;
私人帐户;
私有整数最大值;
}
主要内容:

publicstaticvoidmain(String[]args)抛出InterruptedException{
银行b=新银行(NACCOUNTS,初始余额);
线程[]线程=新线程[NACCOUNTS];
//为每个帐户启动一个线程
对于(int i=0;i
我不知道您的确切问题,但您的代码中有一些与此相关的内容:

  • 您的
    transfer()
    方法有两个不同的
    synchronized
    块,但似乎执行了应该在它们之间进行保护的操作

  • 不要信任基元
    boolean
    变量进行同步。当您使用多个线程时,应该使用

  • 现在更新,我对问题有了更好的理解:

    这里的问题是,您正在尝试以其设计者不希望的方式使用
    synchronized
    。如果要进行同步,可以选择一个对象,然后说“一次只有一个线程可以操作这个对象”。使用
    synchronized(this)
    或声明
    public static void main(String[] args) throws InterruptedException {
        Bank b = new Bank(NACCOUNTS, INITIAL_BALANCE);
        Thread[] threads = new Thread[NACCOUNTS];
        // Start a thread for each account
        for (int i = 0; i < NACCOUNTS; i++) {
            threads[i] = new TransferThread(b, i, INITIAL_BALANCE);
            threads[i].start();
        }
        // Wait for all threads to finish
        for (int i = 0; i < NACCOUNTS; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException ex) {
                // Ignore this
            }
        }
        b.test();
    }
    
        if (accounts[from].withdraw(amount)) {
            incrementTransacts(); //synchronzied method increments transactsInProgress
            accounts[to].deposit(amount);
            decrementTransacts(); //synchronized method
        }
    
    class Account {
       private final AtomicInteger balance = new AtomicInteger(0);
       ...
       public int withdraw(int amount) {
            // loop to get the money in a thread-safe manner
            while (true) {
               // get current balance
               int current = balance.get();
               if (current < amount) {
                   // not enough funds
                   return 0;
               }
               // update the balance atomically if it is still current
               if (balance.compareAndSet(current, current - amount)) {
                   return amount;
               }
               // someone else beat me to it so loop and get new balance
           }
       }
    
       public void deposit(int amount) {
           // similar but without the not-enough-funds check and with a +
       }