以下是非線程安全執行流行的丈夫妻子銀行賬戶問題。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