I wrote the following code to achieve a correctly behaving amount transfer scenario. Even after adding synchronisation on each method, I still see "system inconsistent" error after running the program for sometime. I am not sure why I am getting that. Any help here is appreciated.
I wrote the following code to achieve a correctly behaving amount transfer scenario. Even after adding synchronisation on each method, I still see "system inconsistent" error after running the program for sometime. I am not sure why I am getting that. Any help here is appreciated.
package concurrent;
public class MoneyTransfer {
static void makeTransfer(Account fromAccount, Account toAccount, long amount) {
synchronized(MoneyTransfer.class) {
fromAccount.withdraw(amount);
toAccount.deposit(amount);
}
}
public static void main(String a[]) {
Account accA = new Account("a", 1000000);
Account accB = new Account("b", 1000000);
Thread t1 = new Thread(new MoneyTransferTask(100, accA, accB), "t1");
Thread t2 = new Thread(new MoneyTransferTask(100, accA, accB), "t2");
Thread t3 = new Thread(new MoneyTransferTask(100, accA, accB), "t3");
Thread t4 = new Thread(new MoneyTransferTask(100, accA, accB), "t4");
Thread t5 = new Thread(new MoneyTransferTask(100, accA, accB), "t5");
Thread t11 = new Thread(new MoneyTransferTask(100, accA, accB), "t11");
Thread t12 = new Thread(new MoneyTransferTask(100, accA, accB), "t12");
Thread t13 = new Thread(new MoneyTransferTask(100, accA, accB), "t13");
Thread t14 = new Thread(new MoneyTransferTask(100, accA, accB), "t14");
Thread t15 = new Thread(new MoneyTransferTask(100, accA, accB), "t15");
Thread t6 = new Thread(new MoneyTransferTask(100, accB, accA), "t6");
Thread t7 = new Thread(new MoneyTransferTask(100, accB, accA), "t7");
Thread t8 = new Thread(new MoneyTransferTask(100, accB, accA), "t8");
Thread t9 = new Thread(new MoneyTransferTask(100, accB, accA), "t9");
Thread t10 = new Thread(new MoneyTransferTask(100, accB, accA), "t10");
Thread t = new Thread(new PrintBalancesTask(accA, accB), "t");
t.start();
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
t8.start();
t9.start();
t10.start();
t11.start();
t12.start();
t13.start();
t14.start();
t15.start();
}
}
class MoneyTransferTask implements Runnable {
int amount;
Account fromAccount;
Account toAccount;
public MoneyTransferTask(int amount, Account fromAccount, Account toAccount) {
this.amount = amount;
this.fromAccount = fromAccount;
this.toAccount = toAccount;
}
public void run() {
while(true) {
MoneyTransfer.makeTransfer(fromAccount, toAccount, amount);
try {
Thread.sleep(100);
}catch(InterruptedException ie) {
System.out.println("Thread " + Thread.currentThread().getName() + " interrupted");
}
}
}
}
class PrintBalancesTask implements Runnable {
Account accA;
Account accB;
public PrintBalancesTask(Account accA, Account accB) {
this.accA = accA;
this.accB = accB;
}
public void run() {
while(true) {
System.out.println("AccA Balance " + accA.getBalance());
System.out.println("AccB Balance " + accB.getBalance());
if(accA.getBalance() + accB.getBalance() != 2000000) {
System.out.println("AccA Balance " + accA.getBalance());
System.out.println("AccB Balance " + accB.getBalance());
throw new IllegalStateException("System inconsistent");
}
try {
Thread.sleep(5);
}catch(InterruptedException ie) {
System.out.println("Thread " + Thread.currentThread().getName() + " interrupted");
}
}
}
}
class Account {
String accountId;
long balance;
Account(String accountId, long balance) {
this.accountId = accountId;
this.balance = balance;
}
synchronized long getBalance() {
return balance;
}
synchronized void withdraw(long amount) {
balance = balance - amount;
}
synchronized void deposit(long amount) {
balance = balance + amount;
}
}
Your code should work just fine, the issue is with your checker:
if(accA.getBalance() + accB.getBalance() != 2000000) {
The accA.getBalance()
may be performed before some transfer, while accB.getBalance()
will be performed after that transfer.
Try adding synchronized(MoneyTransfer.class)
there:
synchronized(MoneyTransfer.class) {
if(accA.getBalance() + accB.getBalance() != 2000000) {
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.