首页 > 解决方案 > 同步的多线程 Java 应用程序在每 100 次左右运行中有 1 次以 Livelock 或 Deadlock 结束

问题描述

我目前正在处理以银行帐户为例的生产者/消费者问题示例。规则很简单;您必须通过银行账户移动 3 种货币,并且一旦存入一种货币,另一种货币不能被存入,直到余额再次为 0。

我已经实现了我认为是一个合理的逻辑解决方案,但我注意到在运行程序几百次之后,不时地(1/100ish 运行)程序死锁或活锁。我不确定如何找出差异。但我似乎无法发现其根源。

如果有人能解释为什么会发生这种情况,我将不胜感激,据我所知,逻辑对我来说似乎是合理的,但显然我错过了一些东西。

代码如下

package com.lab9;

public class Account
{
    Currency balance;

//    private static boolean deposited = false;

    Account(double amt, String currency)
    {
        this.balance = new Currency(amt, currency);
    }
    public synchronized void deposit(Currency depositAmt)
    {
       // System.out.println("Starting Deposit");
        while (this.balance.getAmount() != 0.0)
        {
            try
            {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.balance.deposit(depositAmt);
        notifyAll();

    }
    public synchronized void withdrawal(Currency withdrawal)
    {
        //System.out.println("Starting Withdrawal");

        while (this.balance.getCurrency() != withdrawal.getCurrency() )
        {
            try
            {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
            this.balance.withdrawal(withdrawal.getAmount());
            this.balance.setCurrency();
            notifyAll();

    }
}

package com.lab9;

public class Currency
{
    private double amount;
    private String currency;

    Currency(double amount, String currency)
    {
        this.amount = amount;
        this.currency = currency;
    }

    public double getAmount() {
        return amount;
    }

    public String getCurrency() {
        return currency;
    }
    public void deposit(Currency deposit)
    {
        this.amount += deposit.getAmount();
        this.currency = deposit.getCurrency();
        System.out.println("Deposit Successful of amount: " + deposit.getAmount() );
    }
    public void withdrawal(double amt)
    {
        if(this.amount >= amt)
        {
            amount -=amt;
            System.out.println("Withdrawal Successful Amount of:" + amt);
        }
    }
    public void setCurrency()
    {
        this.currency = "";
    }

}


package com.lab9;

public class Main
{
    public static void main(String...args)
    {
        Account strangeAccount = new Account(0.0, "");
        Currency[] transfers = {
                new Currency(1.0,"Dollars"),
                new Currency(2.0,"Euros"),
                new Currency(3.0,"Pounds")
        };
        for(var t : transfers)
        {
            new Thread(() -> strangeAccount.deposit(t)).start();
        }
        for(var t : transfers)
        {
            new Thread(() -> strangeAccount.withdrawal(t)).start();
        }
    }
}

标签: javamultithreading

解决方案


推荐阅读