簡體   English   中英

在現實世界中處理並發的銀行交易請求

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM