我需要使用鎖結構,并編輯以下方法以并行執行:
public void Withdraw(int amountToWithdraw)
{
if (amountToWithdraw <= 0)
{
throw new ArgumentException("The amount should be greater than 0.");
}
if (amountToWithdraw > MaxAmountPerTransaction)
{
throw new ArgumentException($"The value {amountToWithdraw} exceeds transaction limit: {MaxAmountPerTransaction}.");
}
if (amountToWithdraw > Amount)
{
throw new ArgumentException("Insufficient funds.");
}
WithdrawAndEmulateTransactionDelay(amountToWithdraw);
}
這是結果
private readonly object balanceLock = new object();
public void Withdraw(int amountToWithdraw)
{
if (amountToWithdraw <= 0)
{
throw new ArgumentException("The amount should be greater than 0.");
}
if (amountToWithdraw > MaxAmountPerTransaction)
{
throw new ArgumentException($"The value {amountToWithdraw} exceeds transaction limit: {MaxAmountPerTransaction}.");
}
if (amountToWithdraw > Amount)
{
throw new ArgumentException("Insufficient funds.");
}
lock (balanceLock)
{
WithdrawAndEmulateTransactionDelay(amountToWithdraw);
}
}
這是對不應更改的方法 WithdrawAndEmulateTransactionDelay 的描述
private void WithdrawAndEmulateTransactionDelay(int amountToWithdraw)
{
Thread.Sleep(1000);
Amount -= amountToWithdraw;
}
但是,單元測驗失敗了。我的代碼中的錯誤在哪里?
uj5u.com熱心網友回復:
看來,您應該將最后一個驗證放在鎖中:在您當前的實作中,有可能
- 執行緒 #1 嘗試撤銷
cash1,這是有效cash1 < Account的 (),驗證通過 - 執行緒 #2 嘗試撤銷
cash2,這是有效cash2 < Account的 (),驗證通過 - 然而
cash1 cash2 > Account - 執行緒 #1
WithdrawAndEmulateTransactionDelay現在呼叫Amount == Amount - cash1 < cash2 - 執行緒 #2 呼叫
WithdrawAndEmulateTransactionDelay; 因為Amount - cash1 < cash2你的測驗失敗了
private readonly object balanceLock = new object();
public void Withdraw(int amountToWithdraw) {
// These validations are not depended on Amount, they don't want lock
if (amountToWithdraw <= 0)
throw new ArgumentOutOfRangeException(nameof(amountToWithdraw),
"The amount should be greater than 0.");
if (amountToWithdraw > MaxAmountPerTransaction)
throw new ArgumentOutOfRangeException(nameof(amountToWithdraw),
$"The value {amountToWithdraw} exceeds transaction limit: {MaxAmountPerTransaction}.");
// from now on we start using Amount, so we need the lock:
lock (balanceLock) {
if (amountToWithdraw > Amount)
throw new ArgumentException("Insufficient funds.", nameof(amountToWithdraw));
WithdrawAndEmulateTransactionDelay(amountToWithdraw);
}
}
uj5u.com熱心網友回復:
我也會避免所有這些例外。錯誤的輸入是這個代碼通常是意料之中的,所以它并不例外。
試試這個代碼:
public TransactionStatus Withdraw(int amountToWithdraw)
{
bool successful = false;
string message = "OK";
int balanceBefore = Amount;
int balanceAfter = Amount;
if (amountToWithdraw <= 0)
{
message = "The amount should be greater than 0.";
}
else if (amountToWithdraw > MaxAmountPerTransaction)
{
message = $"The value {amountToWithdraw} exceeds transaction limit: {MaxAmountPerTransaction}.";
}
else
{
lock (balanceLock)
{
if (amountToWithdraw > Amount)
{
message = "Insufficient funds.";
}
else
{
Thread.Sleep(1000);
Amount -= amountToWithdraw;
successful = true;
balanceAfter = Amount;
}
}
}
return new TransactionStatus()
{
Successful = successful, Message = message, BalanceBefore = balanceBefore, BalanceAfter = balanceAfter
};
}
public struct TransactionStatus
{
public bool Successful;
public string Message;
public int BalanceBefore;
public int BalanceAfter;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/481890.html
