如何使基于ConcurrentHashMap的方法线程安全的?

问题描述 投票:2回答:2

对于并发/多线程学习的目的,我开发将由多个用户可以同时调用一个小的汇款API。我的“数据库”是一个ConcurrentHashMap<String, Double>,该键/值对代表的帐户ID和其目前的平衡。

我知道一个的ConcurrentHashMap(get()put()等)的单一操作是线程安全的,但取款/存款方式将有几种方法调用,最终将使它不是线程安全的。

我的问题:如何设计我的退出/存款方式是线程安全的吗?起初,我想过让他们synchronized,但是这并没有任何意义,因为我会被扔掉的细粒度的ConcurrentHashMap同步的内置机制的罚款。

这些都是我的退出,存款方式(不担心Double这里的钱,那是无关紧要在这种情况下):

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);
}

我希望我已经说清楚了关于我的问题。任何帮助,将真正的赞赏。

java multithreading concurrency concurrenthashmap
2个回答
2
投票

我不认为这是可以解决这样的任务只是用ConcurrentHashMap的一些原子类型。

试想一个情况下,当从一个账户的钱已经转移到另一个。在这种情况下,你需要同步两个帐户同时没有一个地图元素,但。这就是所谓的交易。所以,你需要做的就是实现交易。交易应该锁定所有受影响的acounts和整理后释放他们。

作为另一种选择,你可以只创建线程安全的队列,交易和做的所有交易sequently,你会不会需要也不ConcurrentHashMap的nither同步,但可能这是不是你正在试图研究的一部分。


1
投票

Java的内部有并发多种解决方案,以使用正确的,你需要回答一个简单的问题:我的应用程序的大部分时间是什么?读或写操作?

如果它执行写操作(撤/存款)我会建议使用java.util.concurrent.atomic.DoubleAdder实例,而不是Double这将保证线程安全和提高你的应用程序吞吐量在写入方面。

在一般情况下,此类应用适合于演员模型。每个帐户可以由一个演员来表示。演员将支持一些消息类型,例如:抽取/存款/总。 AKKA framework是角色模型的一个很好的实施。

© www.soinside.com 2019 - 2024. All rights reserved.