Java中的线程安全交换 [英] Thread safe swapping in Java

查看:98
本文介绍了Java中的线程安全交换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一种方法可以接收两个银行帐户作为输入并交换它们的值:

I have a method which receives two bank account as inputs and swap their values :

Public void TransferAccount(AccountID  id1, AccountID id2){
    Account a1 = id1.GetAccount();
    Account a2 = id2.GetAccount();

    //Swap amounts.

    Temp = a1.Balance;
    a1.Balance = a2.Balance;
    a2.Balance = Temp;
}

我想使该方法成为线程安全的,并具有尽可能高的性能(我想这意味着我们可能无法使该方法同步),我们还必须注意死锁,

I want to make this method to be thread-safe with the highest possible performance (I guess it means we may not make the method synchronized) , we have also to be careful about the deadlock ,

我想到了以下解决方案:

I thought of the following solution :

Public void TransferAccount(AccountID  id1, AccountID id2){
    Account a1 = id1.GetAccount();
    Account a2 = id2.GetAccount();

//Swap amounts.
    synchronized(a1){
        wait(a2);
        synchronized(a2){
            Temp = a1.Balance;
            a1.Balance = a2.Balance;
            a2.Balance = Temp;
        }
    }
}

在性能方面是否有更好的实现方式?顺便说一句,这是线程安全的吗?

Is there any better implementation in terms of performance ? and by the way , is this thread-safe at all ?

推荐答案

您的代码会出现死锁.如果一个线程调用swap(a2, a1)而另一个线程调用swap(a1, a2),则将出现死锁.

Your code is subject to deadlock. If a thread calls swap(a2, a1) while another thread calls swap(a1, a2), you'll have a deadlock.

您必须确保始终以相同的顺序锁定帐户.例如,假设所有帐户均由唯一ID标识,

You must make sure that you always lock your accounts in the same order. For example, assuming all the accounts are identified by a unique ID,

public void swap(Account a1, Account a2) {
    Account first = a1;
    Account second = a2;

    if (a1.getId().compareTo(a2.getId()) > 0) {
        first = a2;
        second = a1;
    }

    synchronized (first) {
        synchronized (second) {
            // swap the balances
        }
    }
}

另一个大问题是您使用公共字段访问帐户余额.几乎不应该使用公共字段,尤其是当多个线程访问一个对象时,尤其不要使用公共字段.使用访问器方法,并确保它们正确同步,否则交换后另一个线程将看不到新余额.必须始终以同步方式访问每个共享状态.

Another big problem is that you access the balance of an account using a public field. Public fields should almost never be used, and especially not when an object is accessed by multiple threads. Use accessor methods, and make sure they're properly synchronized, or another thread won't see the new balances after the swap. Every shared state must always be accessed in a synchronized way.

但是与您的代码相关的第一件事是使其编译,并遵守Java命名约定.

But the first thing to do with your code is to make it compile, and respect the Java naming conventions.

这篇关于Java中的线程安全交换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆