假设我要实现一个非常简单的Bank Account类,并且要注意并发和多线程问题,

即使synchronizedbalance,也使以下方法AtomicInteger是一个好主意吗?

另一方面,如果我们将所有方法都同步了,那么就不再使用AtomicInteger了,对吗?

import java.util.concurrent.atomic.AtomicInteger;


public class Account {
    AtomicInteger balance;
    public synchronized int checkBalance(){
        return this.balance.intValue();
    }
    public synchronized void deposit(int amount){
        balance.getAndAdd(amount);
    }
    public synchronized boolean enoughFund(int a){
        if (balance.intValue() >= a)
            return true;
        return false;
    }
    public synchronized boolean transfer_funds(Account acc, int amount){ // dest : acc
        if (enoughFund(amount)){
            withdraw(amount);
            acc.deposit(amount);
            return true;
        }
        return false;
    }
    public synchronized boolean withdraw(int amount){
        if (checkBalance() < amount)
            return false;
        balance.getAndAdd(-1 * amount);
        return true;
    }
}

最佳答案

将您的金额声明为AtomicInteger不会阻止线程在方法执行过程中被抢占(如果未同步)。因此,例如,如果您的方法transfer_funds没有以任何方式同步,即使您的金额为AtomicInteger,您也可能会得到意外的结果

public /* synchronized */ boolean transfer_funds(Account acc, int amount){ // dest : acc
        if (enoughFund(amount)){
            withdraw(amount);  // <- thread can be preempted in the middle of method execution
            acc.deposit(amount);
            return true;
        }
        return false;
    }

这些问题称为比赛条件。一个可能的示例是,当两个线程尝试从同一帐户转移资金时。当一个线程确定存在enoughFund来执行信用转帐时,该线程可能会被抢占,同时另一个线程可以从该帐户开始转帐资金。当第一个线程再次开始处理时,它不会再次检查是否有enoughFunds来执行信用转移(他已经检查过了,但是他的知识可能已经过时了),但是转到下一个执行行。这样,您可能无法获得一致的结果。您可以更改所有帐户开始时的总金额。

Cay Horstmann的Core Java书中对此方面有很好的解释-此处免费提供chapter about synchronization。它详细描述了您要问的几乎完全相同的问题。

关于java - 使用AtomicInteger时进行同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17253260/

10-10 22:31