[英]Handling Concurrent requests for a Bank Transaction in the real world
我嘗試在一個帳戶上執行多次存款/取款交易的經典銀行余額問題。
我已經同步了帳戶類中的兩個方法,並且只有在我加入所有線程后(等待執行完成),帳戶余額才在執行結束時為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
。
我已經同步了兩種方法...
所以我正在考慮一個現實世界的情況...每次報告的余額是否不正確,因為同一帳戶上還有其他線程在運行?
好吧,這取決於您所說的“正確的平衡”。 如果其他線程可以在您請求它的時間和打印它的時間之間更改它,那么正確的平衡是什么?
在多線程環境中,“正確”的含義的不同想法被稱為一致性模型 。
一種很容易理解的一致性模型稱為靜態一致性 。 如果您的程序是靜態一致的,則意味着在所有線程同時處於空閑狀態的任何時候,平衡都是正確的(這里的“ idle”表示做任何不影響平衡的事情)。 定義很容易,但是測試起來可能很棘手:如果沒有這樣的時刻發生怎么辦?
另一個一致性模型稱為線性化 。 線性化的簡單定義是,如果每次且在某個線程的某個確切時刻釋放用於保護平衡的鎖時,“天平”正確時,您的程序就可以線性化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.