下面是流行的丈夫妻子银行账户问题的非线程安全实现。
(一个线程先检查账户,在同一个线程进行提现之前,另一个线程进行提现操作,从而破坏了代码)。
如果我们在执行 Demo.java 文件后查看程序的日志。很明显,“妻子线程”不是从主内存中读取 AtomicInteger 数量的值。
另外,我用普通的“volatile int”尝试了同样的例子。但同样,我面临同样的问题:-“妻子线程没有从主存储器中读取数量整数的值。”
请解释这种行为以帮助我理解这个概念。请在下面找到代码:-
AtomicBankAccount.java
package pack;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicBankAccount {
private AtomicInteger amount ;
public AtomicBankAccount(int amt) {
this.amount = new AtomicInteger(amt) ;
}
// returns
// -1 for insufficient funds
// remaining balance without subtracting from actual amount for sufficient funds
public int check(int amtToWithdraw){
if(amtToWithdraw <= amount.get()){
System.out.println(Thread.currentThread().getName() + " checks amount : " + amount.get() + ". Remaining ammount after withdrawl should be : " + (amount.get() - amtToWithdraw));
return (amount.get() - amtToWithdraw) ;
}else{
return -1 ;
}
}
// returns
// remaining balance after subtracting from actual amount
public int withdraw(int amtToWithdraw){
amount.getAndAdd(-amtToWithdraw) ;
System.out.println(Thread.currentThread().getName() + " withdraws " + amtToWithdraw + ". Remaining : " + amount.get() + " [latest updated value of account in main memory]");
return amount.get() ;
}
public int getAmount(){
return amount.get() ;
}
}
AtomicWithdrawThread.java
package pack;
public class AtomicWithdrawThread extends Thread{
private AtomicBankAccount account ;
public AtomicWithdrawThread(AtomicBankAccount acnt, String name) {
super(name) ;
this.account = acnt ;
}
@Override
public void run() {
int withDrawAmt = 2 ;
int remaining = 0 ;
while(true){
if( (remaining = account.check(withDrawAmt)) != -1 ){
int temp = account.withdraw(withDrawAmt) ;
if(temp != remaining){
System.out.println("[Race condition] " + Thread.currentThread().getName());
System.exit(1) ;
}
}else{
System.out.println("Empty Account....");
System.exit(1) ;
}
}
}
}
演示.java
package pack;
public class Demo {
public static void main(String[] args) {
AtomicBankAccount bankAccount = new AtomicBankAccount(1000) ;
AtomicWithdrawThread husbandThread = new AtomicWithdrawThread(bankAccount, "husband") ;
AtomicWithdrawThread wifeThread = new AtomicWithdrawThread(bankAccount, "wife") ;
husbandThread.start() ;
wifeThread.start() ;
}
}
最好的祝福,
仪式