繁体   English   中英

在两个 String 对象上同步

[英]Synchronize on two String objects

我只找到了一个字符串 object 同步的答案,而不是两个。

这不是一项真正的任务,而是一项任务。 我有 SomeLibrary 可以将钱从一个帐户转移到另一个帐户。 我无法访问帐户 object 来锁定它。 我只能使用 SomeLibrary.transfer(String from, String to),它不是线程安全的。 我有将帐户 ID 作为字符串的方法。 我需要在没有死锁的情况下锁定这两个字符串。

到目前为止我所做的是:

  1. 使用.intern 方法创建了新的字符串(String fr = from.intern())。 但这是不好的做法,我不允许使用这种方法。 但它奏效了。

  2. 从旧字符串创建新字符串(String fr = new String(from))。 这也有效(我没有死锁),但我怀疑这个解决方案。

还有其他方法可以锁定两个字符串吗?

我尝试使用 ConcurrentHashMap 并将字符串放在那里,但它没有用。

可能有一种方法可以将字符串放入某些对象中,但是应该在哪里创建这些对象? 我可以在 transfer() 中创建它们,但是在局部变量上同步也不是好习惯。

我的方法是:

public void transfer(String from, String to, int amount) {
        String fr = new String(from);
        String too = new String(to);

        int fromHash = System.identityHashCode(fr);
        int toHash = System.identityHashCode(too);

        if (fromHash < toHash) {
            synchronizedTransfer(from, to, amount, fr, too);
        } else if (fromHash > toHash) {
            synchronizedTransfer(to, from, amount, too, fr);
        } else {
            synchronized (tieLock) {
                synchronizedTransfer(from, to, amount, fr, too);
            }
        }
    }

private void synchronizedTransfer(String from, String to, int amount, String fr, String too) {
        synchronized (fr) {
            synchronized (too) {
                SomeLibrary.transfer(from, to);
            }
        }
    }

您可以使用嵌套的同步块在两个对象上同步。 为了防止任何死锁,我会按字典顺序比较两个字符串:

public void transfer(String from, String to, int amount) {
        int comparingResult = from.compareTo(to);
        
        if (comparingResult > 0) {
            synchronized (from) {
                synchronized (to) {
                    SomeLibrary.transfer(from, to);
                }
            }
        } else if (comparingResult < 0) {
            synchronized (to) {
                synchronized (from) {
                    SomeLibrary.transfer(from, to);
                }
            }
        } else {
            if (from == to) { // Do not use equals() here
                synchronized (from) {
                    SomeLibrary.transfer(from, to);
                }
            } else {
                throw new UnsupportedOperationException();
            }
           
        }
    }

else部分是可选的,取决于您可以在同一个帐户之间转移资金这一事实,在我看来,这有点无用。

必须明确的是,对于传输(from, to),所有 (from, ), ( , from), (*, to), (to, *)传输可能需要被保护。

做到这一点的唯一方法是同步从和同步到。 当有传输(到,从)时,这可能会导致死锁 为此,可以订购 from 和 to 以便同步 AAA 在同步 BBB 之前。

另一种方法是在可以回滚的事务中进行原子存款(from, -amount),存款(to, amount)并完成所有操作。

现在同步 object:这必须是唯一的 Object 实例。 您可以使用帐户 ID 字符串,如Map ( Set )。 因此,您有一个独特的 object 作为 map 中的键。 当然 map 操作也受到并发的影响,使用: Collections.synchronizedMap 您需要更新它,添加/删除帐户 ID。

由于事务是一个单独的主题,因此按规范顺序嵌套两个同步。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM