导致死锁的代码与防止死锁的代码有什么区别?需要解释代码示例

问题描述 投票:0回答:1

我给出了一个Banking示例的代码,我试图弄清楚这是否会产生死锁。如果是这样,代码的哪一部分实现了它?我还想知道如何改变代码以防止死锁。我知道这与方法的排序有关,但这段代码特别让我感到困惑。我是网络编程的新手,所以我对这个话题仍然有些困惑。

我用Java写的。

公共类银行{

public Bank(int n, double initialBalance)
{
    accounts = new double[n];
    Arrays.fill(accounts, initialBalance);
    bankLock = new ReentrantLock();
    sufficientFunds = bankLock.newCondition();
}

public synchronized void transfer(int from, int to, double amount) throws InterruptedException
{
     bankLock.lock();
     try
     {
        while (accounts[from] < amount)
           sufficientFunds.await();
        System.out.print(Thread.currentThread());
        accounts[from] -= amount;
        System.out.printf(" %10.2f from %d to %d", amount, from, to);
        accounts[to] += amount;
        System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
        sufficientFunds.signalAll();
     }
     finally
     {
        bankLock.unlock();
     }
}

public synchronized double getTotalBalance()
{
    bankLock.lock();
     try
     {
        double sum = 0;

        for (double a : accounts)
           sum += a;

        return sum;
     }
     finally
     {
        bankLock.unlock();
     }
}

public int size()
{
    return accounts.length;
}

公共类DeadlockApp {

public static void main(String[] args) 
{
    Bank bank = new Bank(NACCOUNTS,INITIAL_BALANCE);
    for (int i = 0; i< NACCOUNTS; i++)
    {
        int fromAccount = i;
        Runnable r = () -> 
        {
            try 
            {
                while (true) 
                {
                    int toAccount = (int) (bank.size() * Math.random());
                    double amount = MAX_AMOUNT * Math.random();
                    bank.transfer(fromAccount, toAccount, amount);
                    Thread.sleep((int)(DELAY * Math.random()));
                }
            }
            catch (InterruptedException e)
            {
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}

当我运行代码时,它非常慢,只产生了两个结果,所以我无法分辨是否是持续的死锁或者我的IDE只是滞后。

java deadlock
1个回答
0
投票

死锁的基本要求是两个或多个线程尝试获取一系列锁,但是以不同的顺序获取它们。

你有两个锁,但你的线程都执行相同的代码,它具有固定的锁获取顺序,并且可以递归获取两个锁,因此没有死锁。

更具体地说,由于它是transfer,一次只有一个线程在synchronized中执行。

锁按此顺序获取:

  1. 银行监控(通过'同步'转账)
  2. 银行锁(转让)
  3. 银行再次监控(在getTotalBalance上'同步') - 但我们已经持有它,因此它不会阻止
  4. banklock(在getTotalBalance中),但我们已经拥有它,所以它不会阻止

没有死锁,所以还有其他原因导致“缓慢”。我的猜测是随机行动需要多长时间来建立足够的资金。

© www.soinside.com 2019 - 2024. All rights reserved.