当前位置: 首页 > 面试题库 >

更好的解决方案,而不是Java中的嵌套同步块?

别兴国
2023-03-14
问题内容

我有一Bank堂课,有一个清单Account。银行有一种transfer()将价值从一个帐户转移到另一个帐户的方法。这个想法是同时锁定转帐中的fromto帐户。

为了解决这个问题,我有以下代码(请记住,这是一个非常琐碎的示例,因为仅仅是一个示例):

public class Account {
    private int mBalance;

    public Account() {
        mBalance = 0;
    }

    public void withdraw(int value) {
        mBalance -= value;
    }

    public void deposit(int value) {
        mBalance += value;
    }
}

public class Bank {
    private List<Account> mAccounts;
    private int mSlots;

    public Bank(int slots) {
        mAccounts = new ArrayList<Account>(Collections.nCopies(slots, new Account()));
        mSlots = slots;
    }

    public void transfer(int fromId, int toId, int value) {
        synchronized(mAccounts.get(fromId, toId)) {
            synchronized(mAccounts.get(toId)) {
                mAccounts.get(fromId).withdraw(value);
                mAccounts.get(toId).deposit(value);
            }
        }
    }
}

这有效,但不能防止 死锁 。要解决此问题,我们需要将同步更改为以下内容:

synchronized(mAccounts.get(Math.min(fromId, toId))) {
    synchronized(mAccounts.get(Math.max(fromId, toId))) {
        mAccounts.get(fromId).withdraw(value);
        mAccounts.get(toId).deposit(value);
    }
}

但是编译器警告我有关 嵌套的同步块
,我相信这是一件坏事吗?另外,我不太喜欢最大/最小解决方案(我不是那个想法的提出者),如果可能的话,我想避免这种情况。

如何解决以上两个问题?如果我们可以锁定多个对象,则可以同时锁定fromto帐户,但据我所知不能这样做。那有什么解决方案?


问题答案:

锁排序确实是解决方案,所以您是对的。编译器会警告您,因为它无法确保 所有 锁定 均已按
顺序进行—它不够聪明,无法检查您的代码,并且不够聪明,知道可能还有更多的代码。

另一种解决方案是锁定一个封闭的对象,例如,对于一个用户帐户内的转账,您可以锁定用户。用户之间的转移并非如此。

话虽如此,您可能不必依靠Java锁定来进行传输:您需要一些数据存储,通常是数据库。如果使用数据库,锁定将移至存储。仍然适用相同的原则:您订购锁以避免死锁;您可以升级锁以简化锁定。



 类似资料:
  • 问题内容: 我在Heinz Kabutz的 Java专家 通讯版本中看到了这一点,尽管Kabutz博士的文章的其余部分(乃至全部)都得到了很好的解释和详细说明,但他似乎掩盖了这段代码的作用,或更重要的是,它的意义是: 嵌套块的含义是什么?这如何影响尝试执行的不同线程? 问题答案: 有两个可能需要注意的问题 如果使用等待/通知,嵌套锁很容易导致死锁。这是为什么的解释。http://tutorials

  • 本文向大家介绍PHP中实现MySQL嵌套事务的两种解决方案,包括了PHP中实现MySQL嵌套事务的两种解决方案的使用技巧和注意事项,需要的朋友参考一下 一、问题起源 在MySQL的官方文档中有明确的说明不支持嵌套事务: 但是在我们开发一个复杂的系统时难免会无意中在事务中嵌套了事务,比如A函数调用了B函数,A函数使用了事务,并且是在事务中调用了B函数,B函数也有一个事务,这样就出现了事务嵌套。这时候

  • 本文向大家介绍Fragment 多层嵌套方法调用问题的解决方案,包括了Fragment 多层嵌套方法调用问题的解决方案的使用技巧和注意事项,需要的朋友参考一下 Fragment的产生与介绍 Android运行在各种各样的设备中,有小屏幕的手机,超大屏的平板甚至电视。针对屏幕尺寸的差距,很多情况下,都是先针对手机开发一套App,然后拷贝一份,修改布局以适应平板神马超级大屏的。难道无法做到一个App可

  • 问题内容: 有谁能举例说明同步方法优于同步块的优势吗? 问题答案: 在块上使用同步方法没有明显的优势。 也许唯一的一个(但我不会称其为优势)是你不需要包括对象引用。 方法: 块: 看到?完全没有优势。 但是,块确实比方法具有优势,主要是在灵活性方面,因为你可以将另一个对象用作锁,而同步该方法将锁定整个对象。 比较: 与 同样,如果方法变大,你仍然可以将同步部分分开:

  • 本文向大家介绍详解MySQL实时同步到Oracle解决方案,包括了详解MySQL实时同步到Oracle解决方案的使用技巧和注意事项,需要的朋友参考一下 1 需求概述 将MySQL5.6生产库多张表的数据实时同步到Oracle11g数据仓库,MySQL历史数据700G,平均每天产生50G左右日志文件,MySQL日志空间50G,超过后滚动删除日志文件。整个同步过程不可影响MySQL业务操作。 2 技术

  • 本文向大家介绍用Promise解决多个异步Ajax请求导致的代码嵌套问题(完美解决方案),包括了用Promise解决多个异步Ajax请求导致的代码嵌套问题(完美解决方案)的使用技巧和注意事项,需要的朋友参考一下 问题 前端小同学在做页面的时候,犯了个常见的错误:把多个Ajax请求顺序着写下来了,而后面的请求,对前面请求的返回结果,是有依赖的。如下面的代码所示: 以上代码有两个问题: *首先就是执行