gpt4 book ai didi

c# - C#锁构造误区(附msdn代码示例)

转载 作者:太空宇宙 更新时间:2023-11-03 14:52:24 26 4
gpt4 key购买 nike

我对使用 C# lock 构造的一件事很感兴趣现在从 MSDN 取样,然后是主要问题:

以下示例使用线程和锁。只要 lock 语句存在,语句 block 就是临界区,balance 永远不会变成负数。

class Account
{
private Object thisLock = new Object();
int balance;

Random r = new Random();

public Account(int initial)
{
balance = initial;
}

int Withdraw(int amount)
{

// This condition never is true unless the lock statement
// is commented out.
if (balance < 0)
{
throw new Exception("Negative Balance");
}

// Comment out the next line to see the effect of leaving out
// the lock keyword.
lock (thisLock)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0; // transaction rejected
}
}
}

public void DoTransactions()
{
for (int i = 0; i < 100; i++)
{
Withdraw(r.Next(1, 100));
}
}
}

class Test
{
static void Main()
{
Thread[] threads = new Thread[10];
Account acc = new Account(1000);
for (int i = 0; i < 10; i++)
{
Thread t = new Thread(new ThreadStart(acc.DoTransactions));
threads[i] = t;
}
for (int i = 0; i < 10; i++)
{
threads[i].Start();
}

//block main thread until all other threads have ran to completion.
foreach (var t in threads)
t.Join();
}
}

我不明白为什么使用lock 帐户余额不会变成负数;它总是以0 余额结束编译。 P.S 对不起我的英语。

最佳答案

在这个例子中,锁按预期工作,在启动多个线程时,它们都会尝试从帐户中退出,这可能会导致非常糟糕的功能。怎么样?
好吧,假设当前余额是 40,线程 1 试图取回 40,线程 2 试图取回 20,如果没有锁,他们都将成功取回,余额将是 -20,这是 Not Acceptable 。

现在您真正关心的是,为什么余额不会变为负数?简单:

lock (thisLock)
{
if (balance >= amount)
{
Console.WriteLine("Balance before Withdrawal : " + balance);
Console.WriteLine("Amount to Withdraw : -" + amount);
balance = balance - amount;
Console.WriteLine("Balance after Withdrawal : " + balance);
return amount;
}
else
{
return 0; // transaction rejected
}
}

锁将确保每个线程只有在余额可用时才会取款,所以条件if (balance >= amount)再加上 if (balance < 0)将确保余额不会变为负值。

如果您记录每个线程提取的金额,您可以看到详细信息:

Console.WriteLine(Withdraw(r.Next(1, 100)));

你会看到他们中的很多人会在一段时间后输出 0,因为账户不再有余额因此 return 0触发器。

关于c# - C#锁构造误区(附msdn代码示例),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51180402/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com