Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions src/edu/temple/cis/c3238/banksim/Account.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package edu.temple.cis.c3238.banksim;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* @author Cay Horstmann
* @author Modified by Paul Wolfgang
Expand All @@ -10,21 +13,29 @@ public class Account {
private volatile int balance;
private final int id;
private final Bank myBank;

public Account(Bank myBank, int id, int initialBalance) {
this.myBank = myBank;
this.id = id;
balance = initialBalance;
}

/*
* getBalance() does not need to be synchronized, despite balance being
* a shared variable, because getBalance() does not modify balance.
**/
public int getBalance() {
return balance;
}

public boolean withdraw(int amount) {
/*
* withdraw() method is synchronized via synchronized keyword in it's
* declaration
**/
public synchronized boolean withdraw(int amount) {
if (amount <= balance) {
int currentBalance = balance;
// Thread.yield(); // Try to force collision
//Thread.yield(); // Try to force collision
int newBalance = currentBalance - amount;
balance = newBalance;
return true;
Expand All @@ -33,15 +44,33 @@ public boolean withdraw(int amount) {
}
}

public void deposit(int amount) {
/*
* synchronized same as withdraw()
**/
public synchronized void deposit(int amount) {
int currentBalance = balance;
// Thread.yield(); // Try to force collision
//Thread.yield(); // Try to force collision
int newBalance = currentBalance + amount;
balance = newBalance;

notifyAll();
}

/*
* implementation of task 4
* this method waits for amount <= balance
**/
public synchronized void waitForSufficientFunds(int amount) {

while (myBank.isOpen() && amount >= balance) {
try {
wait();
} catch (InterruptedException ex) {/*ignore*/}
}
}

@Override
public String toString() {
return String.format("Account[%d] balance %d", id, balance);
}
}
}
80 changes: 71 additions & 9 deletions src/edu/temple/cis/c3238/banksim/Bank.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.temple.cis.c3238.banksim;

import java.util.concurrent.locks.ReentrantLock;
/**
* @author Cay Horstmann
* @author Modified by Paul Wolfgang
Expand All @@ -13,7 +14,10 @@ public class Bank {
private long ntransacts = 0;
private final int initialBalance;
private final int numAccounts;
private final ReentrantLock rlock = new ReentrantLock();

private boolean open = true;

public Bank(int numAccounts, int initialBalance) {
this.initialBalance = initialBalance;
this.numAccounts = numAccounts;
Expand All @@ -25,20 +29,55 @@ public Bank(int numAccounts, int initialBalance) {
}

public void transfer(int from, int to, int amount) {
// accounts[from].waitForAvailableFunds(amount);
if (accounts[from].withdraw(amount)) {
accounts[to].deposit(amount);

if (!open) {
return;
}

/* waiting for amount <= balance via method call */
accounts[from].waitForSufficientFunds(amount);

/* ReentrantLock used to manipulate account balances */
rlock.lock();
try {
if (accounts[from].withdraw(amount)) {
accounts[to].deposit(amount);
}
}
finally {
rlock.unlock();
}

if (shouldTest()) {
test();
}
if (shouldTest()) test();
}

}

public void test() {

int sum = 0;
for (Account account : accounts) {
System.out.printf("%s %s%n",

/*
* the shared part of this method is "account.getBalance"
* hence, we lock that part with a ReentrantLock
**/
rlock.lock();

try {

for (Account account : accounts) {
System.out.printf("%s %s%n",
Thread.currentThread().toString(), account.toString());
sum += account.getBalance();
sum += account.getBalance();
}

}

finally {
rlock.unlock();
}

System.out.println(Thread.currentThread().toString() +
" Sum: " + sum);
if (sum != numAccounts * initialBalance) {
Expand All @@ -51,6 +90,7 @@ public void test() {
}
}


public int size() {
return accounts.length;
}
Expand All @@ -59,5 +99,27 @@ public int size() {
public boolean shouldTest() {
return ++ntransacts % NTEST == 0;
}

/* returns true when the account is open, false otherwise */
public synchronized boolean isOpen() {
return open;
}

/* method to satisfy Task 5;
* closeBank() closes all accounts */
public void closeBank() {

/* the open variable is shared and hence protected */
synchronized (this) {
open = false;
}

/* wake up all waiting threads */
for (Account account : accounts) {
synchronized (account) {
account.notifyAll();
}
}
}

}
}
6 changes: 1 addition & 5 deletions src/edu/temple/cis/c3238/banksim/BankSimMain.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ public static void main(String[] args) {
threads[i] = new TransferThread(b, i, INITIAL_BALANCE);
threads[i].start();
}

// b.test();
System.out.printf("Bank transfer is in the process.\n");
}
}


}
3 changes: 3 additions & 0 deletions src/edu/temple/cis/c3238/banksim/TransferThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,8 @@ public void run() {
int amount = (int) (maxAmount * Math.random());
bank.transfer(fromAccount, toAccount, amount);
}

/* when one bank closes, it calls closeBank (closing them all) */
bank.closeBank();
}
}