为了账号安全,请及时绑定邮箱和手机立即绑定

Java 并发 - 避免同时修改具有相同 ID 的对象的数据结构

Java 并发 - 避免同时修改具有相同 ID 的对象的数据结构

12345678_0001 2023-05-10 15:39:22
对于以下情况,正确的结构是什么:假设我们有一个库存系统(域并不重要,这只是一个例子)并且每个操作都很慢(例如联系外部系统)。它处理 ~ 50 个仓库 (WH)。我可以将库存从一个仓库转移到另一个仓库。我要保证最终库存是正确的我在想的是,我可以并行处理不影响同一个 WH 的请求。例如:请求将 20 件物品从仓库 1 移动到仓库 3将 15 个项目从 2 移动到 5 的请求移动(可以与上一个并行处理)请求将 5 个项目从 3 移动到 6(它应该等待第一个请求完成后再继续)。我在考虑一个线程安全的映射,其中包含我当前正在处理的仓库的所有 ID。有更好的东西吗?
查看完整描述

2 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

我建议您lock为每个Warehouse对象引入一个变量以及一个唯一的整数。您可以使用 anAtomicInteger来确保每个创建的仓库都有其唯一编号


public class Warehouse {

    private static final AtomicInteger numberProvider = new AtomicInteger(0);

    private final int number;

    private final Lock lock = new ReentrantLock();

    // ...

    public Warehouse(...) {

        this.number = numberProvider.incrementAndGet();

        ...

    }

    // ... (getter for number and lock and other methods)

}

这样您就可以始终以“正确”的顺序锁定两个仓库(例如,先锁定较低的数字,然后锁定较高的数字;向后解锁)。这将保证您不会遇到死锁。


public void moveStock(Warehouse from, Warehouse to, int nof) {

    List<Lock> locks = Stream.of(from, to)

        .sorted(Comparator.comparingInt(Warehouse::getNumber))

        .map(Warehouse::getLock)

        .collect(Collectors.toList());


    for(int i=0;i<locks.size();++i) {

        locks.get(i).lock();

    }

    try {

        from.substractStock(nof);

        to.addStock(nof);

    } finally {

        for(int i=locks.size()-1;i>=0;i--) {

            locks.get(i).unlock();

        }

    }

}


查看完整回答
反对 回复 2023-05-10
?
温温酱

TA贡献1752条经验 获得超4个赞

集合将是您正在寻找的数据结构。



查看完整回答
反对 回复 2023-05-10
  • 2 回答
  • 0 关注
  • 130 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信