java - 同步的多线程 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();
}
}
}
解决方案
推荐阅读
- flutter - Flutter - 任务':app:checkDebugAarMetadata'的执行失败
- relational-database - 这个规范化的表有什么问题?
- go - 如何使用 Gin 从动态子目录中提供文件?
- mysql - 带有打字稿的续集不能使用带有类型属性的 .create
- javascript - Service Worker onClick 事件 - 打开并将一些数据传递给 PWA
- python - 使用与列名值匹配的键创建新列
- python - pytorch 对索引子集进行矢量化
- mongodb - MongoDB - 如何在以下模式中提高查询性能?
- git - gitk - 不显示与 glob 或 regexp 不匹配的分支的标签
- nginx - Engintron:Nginx 无法启动