以下是非线程安全执行流行的丈夫妻子银行账户问题。AtomicInteger不从主存储器读取值为非易失性可变参考
(一个线程先检查帐户,并且在同一个线程执行撤销之前,另一个线程执行撤销操作,从而破坏代码)。
如果我们在执行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) ;
}
}
}
}
Demo.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() ;
}
}
最好的问候,
RITS
我知道这种行为,但问题是,妻子线程不能从主内存读取ammount值。说,丈夫在旅途中留下了302卢比。在下一行日志中说,妻子检查了546卢比。 – mogli
啊 - 你是否期望System.out是线程安全的并且不会受到竞争条件的影响? –
是不是System.out线程安全? – mogli