经典的银行余额问题,我试图在一个帐户上执行多次存款/取款交易。
我已经同步了account类中的两个方法,只有加入所有线程(等待执行完成),执行结束时账户余额才为500
所以我正在考虑一个现实世界的场景,其中每个请求都会生成一个新线程来执行事务并返回余额。每次报告的余额是否不正确,因为有其他线程在同一帐户上运行?
这是代码:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
class Account {
private int balance = 0;
Account(int bal){
this.balance =bal;
}
public int getBal() {
return balance;
}
public synchronized void withdraw(int bal){
balance = balance - bal;
}
public synchronized void deposit(int bal){
balance = balance + bal;
}
}
public class TransactionManagerNaiveSync implements Runnable {
Account account;
public TransactionManagerNaiveSync(Account a){
this.account = a;
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
Account a1 = new Account(500);
TransactionManagerNaiveSync t1 = new TransactionManagerNaiveSync(a1);
List<Thread> thread = new ArrayList<Thread>();
for(int i=0;i < 300;i++) thread.add(new Thread(t1));
for(int i=0;i < 300;i++) thread.get(i).start();
for(int i=0;i < 300;i++){
try {
thread.get(i).join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println(" Account Balance in the end : "+ a1.getBal());
System.out.println(" Time Taken : "+(end - start));
}
@Override
public void run() {
//for(int i=0;i < 100;i++)
//{
account.deposit(10);
System.out.println(""+Thread.currentThread().getId()+" Account Balance after deposit : "+account.getBal());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.withdraw(10);
System.out.println(""+Thread.currentThread().getId()+" Account Balance after withdrawal : "+account.getBal());
//}
}
}
平衡可能不正确,因为您没有同步
Account.getBal()
,这意味着您可能无法获得最新值,因为内存可见性保证不可用于对多个线程更新的变量的非同步访问。
简单标记方法
synchronized
。
如果您将余额存储为
AtomicInteger
而不是 int
,也会更容易(并且几乎肯定更高效),因为那时您根本不需要 synchronize
。
我已经同步了这两种方法...
所以我正在考虑一个现实世界的场景...每次报告的余额是否不正确,因为同一帐户上有其他线程在运行?
嗯,这取决于你所说的“正确的平衡”是什么意思。如果其他线程可以在您请求它的时间和您打印它的时间之间更改它,那么正确的平衡是什么? 在多线程环境中,关于“正确”含义的不同想法被称为
一致性模型。 一种非常容易理解的一致性模型称为“静态一致性”。如果您的程序是静态一致的,则意味着当所有线程同时空闲时,平衡在任何时刻都是正确的(这里,“空闲”是指执行任何不影响平衡的操作)。它很容易定义,但测试起来可能很棘手:如果这样的时刻从未发生过怎么办?
另一个一致性模型称为线性化。线性化的一个简单定义是,如果余额每次都“正确”,并且在“精确的瞬间”,当您的一个线程释放用于保护余额的锁时,您的程序就是可线性化的。
使用 @GuardedBy(“这个”)