【问题标题】:Thread safe swapping in JavaJava中的线程安全交换
【发布时间】:2013-06-08 06:23:41
【问题描述】:

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

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

我想让这个方法以尽可能高的性能成为线程安全的(我猜这意味着我们可能不会使方法同步),我们还必须小心死锁,

我想到了以下解决方案:

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

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

【问题讨论】:

  • 我猜这意味着我们可能不会使方法同步 ...我猜这意味着这是家庭作业?
  • 猜错了,下一个请careercup.com/question?id=15903683
  • @BrianRoach:我不明白是什么让你这么想。 OP 说“我需要尽可能高的性能,我想这意味着我不能只制作方法synchronized”。这对我来说并不叫“功课”,尽管它确实叫“缺乏特定的性能要求”。
  • "这种方法是线程安全的,具有尽可能高的性能" 如果你这样做了,一个线程将比使用多个线程快得多。即快 10 倍以上。 vanillajava.blogspot.co.uk/2011/11/…Accounting example
  • 即使是这样,为什么作业这么讨厌SO?我一直不明白这一点。我曾经对我的家庭作业感到困惑。

标签: java multithreading thread-safety


【解决方案1】:

您的代码可能会出现死锁。如果一个线程调用swap(a2, a1),而另一个线程调用swap(a1, a2),就会出现死锁。

您必须确保始终以相同的顺序锁定您的帐户。例如,假设所有帐户都由唯一 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
        }
    }
}

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

但是对您的代码做的第一件事是让它编译,并尊重 Java 命名约定。

【讨论】:

  • 有没有办法只用等待、通知和同步而不考虑订购?
  • 我看不出等待和通知与问题有什么关系。没有理由等待,也没有理由通知另一个线程。
  • 好吧,一个人可以等到另一个完成后再继续,从这个角度来看是不可能使用等待和通知的?
  • 这就是 synchronized 所做的:它阻塞直到监视器被释放。无需等待。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-14
相关资源
最近更新 更多