【问题标题】:Best way to avoid deadlock for several objects transaction?避免多个对象事务死锁的最佳方法?
【发布时间】:2017-12-06 17:47:26
【问题描述】:

我正在寻找死锁示例,偶然发现了这段代码:

package com.example.thread.deadlock._synchronized;

public class BankAccount {
    double balance;
    int id;

    BankAccount(int id, double balance) {
        this.id = id;
        this.balance = balance;
    }

    void withdraw(double amount) {
        // Wait to simulate io like database access ...
        try {Thread.sleep(10l);} catch (InterruptedException e) {}
        balance -= amount;
    }

    void deposit(double amount) {
        // Wait to simulate io like database access ...
        try {Thread.sleep(10l);} catch (InterruptedException e) {}
        balance += amount;
    }

    static void transfer(BankAccount from, BankAccount to, double amount) {
        synchronized(from) {
            from.withdraw(amount);
            synchronized(to) {
                to.deposit(amount);
            }
        }
    }

    public static void main(String[] args) {
        final BankAccount fooAccount = new BankAccount(1, 100d);
        final BankAccount barAccount = new BankAccount(2, 100d);

        new Thread() {
            public void run() {
                BankAccount.transfer(fooAccount, barAccount, 10d);
            }
        }.start();

        new Thread() {
            public void run() {
                BankAccount.transfer(barAccount, fooAccount, 10d);
            }
        }.start();

    }
}

您将如何更改transfer 方法以使其不会导致死锁?第一个想法是为所有帐户创建一个共享锁,但这当然会杀死所有并发。那么有没有一种好方法可以只锁定交易中涉及的两个账户而不影响其他账户?

【问题讨论】:

    标签: java multithreading concurrency synchronized


    【解决方案1】:

    在多锁情况下避免死锁的一种方法是始终以相同的顺序锁定对象。

    在这种情况下,这意味着您将为所有 BankAccount 对象创建一个总排序。幸运的是,我们有一个可以使用的 id,所以您总是可以先锁定较低的 id,然后(在另一个同步块内)锁定较高的 id。

    这假设不存在具有相同 ID 的 BankAccount 对象,但这似乎是一个合理的假设。

    【讨论】:

      【解决方案2】:

      分别使用两个同步块而不是嵌套。

      synchronized(from){
          from.withdraw(amount);
      }
      synchronized(to){
          to.deposit(amount);
      }
      

      所以在调用from.withdraw(amount) 之后,from 上的锁定在它尝试锁定to 之前被释放

      【讨论】:

      • 如果一个成员在交易过程中因为另一笔交易而没有钱怎么办,使用2个同步块会出现问题
      • 你确实意识到这不是交易,对吧?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-17
      • 1970-01-01
      相关资源
      最近更新 更多