簡體   English   中英

如何使基於ConcurrentHashMap的方法線程安全?

[英]How to make a ConcurrentHashMap based method thread safe?

出於並發/多線程學習的目的,我正在開發一個小額轉賬API,該API將由多個用戶同時調用。 我的“數據庫”是ConcurrentHashMap<String, Double> ,其中的鍵/值對表示一個帳戶ID及其當前余額。

我知道ConcurrentHashMap的單個操作( get()put()等)是線程安全的,但是withdraw / deposit方法將具有多個方法調用,這些調用最終將使其變為線程安全的。

我的問題:如何設計我的提現/存款方法是線程安全的? 最初,我考慮過使它們synchronized ,但這沒有任何意義,因為我將丟棄ConcurrentHashMap細粒度內置同步機制。

這些都是我的提款和存款方法(在這里不必擔心Double for money,在這種情況下這無關緊要):

private void deposit(ConcurrentHashMap<String, Double> myDatabase, String fromAccountId, String toAccountId, double amount) {
    if(myDatabase.get(fromAccountId) < amount) {
        throw new MonetaryOperationViolation("Insufficient funds to perform this operation");
    }

    //Add the amount to the receiver's account
    myDatabase.replace(toAccountId, myDatabase.get(toAccountId), c.get(toAccountId) + amount); //key, oldValue, newValue

    //Withdraw it from the sender's account
    withdraw(myDatabase, fromAccountId, amount);
}

private void withdraw(ConcurrentHashMap<String, Double> myDatabase, String accountId, double amount) {
    if(myDatabase.get(accountId) < amount) {
        throw new MonetaryOperationViolation("Insufficient funds to perform this operation");
    }

    myDatabase.replace(accountId, myDatabase.get(accountId), myDatabase.get(accountId) - amount);
}

我希望我已經清楚說明了自己的問題。 任何幫助將不勝感激。

我認為僅通過使用具有某些原子類型的ConcurrentHashMap來解決此類任務是不可能的。

想象一下一種情況,將一個帳戶中的錢轉移到另一個帳戶中。 在這種情況下,您不需要同時在一個Map元素上同步,而是在兩個帳戶上同步。 這稱為交易。 因此,您需要做的是實現事務。 交易應鎖定所有受影響的帳戶,並在完成后釋放它們。

作為另一種選擇,您可以只創建帶有事務的線程安全隊列,然后依次執行所有事務,並且不需要ConcurrentHashMap nither同步,但是這可能與您要研究的部分無關。

Java內部有許多並發解決方案,為了使用正確的並發解決方案,您需要回答一個簡單的問題:我的應用程序大部分時間都在做什么? 讀或寫操作?

如果它執行寫入(撤回/存款),我建議使用java.util.concurrent.atomic.DoubleAdder實例而不是Double這將確保線程安全並在寫入方面增加您的應用程序吞吐量。

通常,此類應用適合Actors模型。 每個帳戶都可以由一個演員代表。 參與者將支持一些消息類型,例如:提款/存款/總計。 AKKA框架是actor模型的出色實現。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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