C# 多线程但不锁定仍能给出正确的结果

C# 多线程但不锁定仍能给出正确的结果,c#,multithreading,C#,Multithreading,我想象结果会是负值,因为没有锁定并且多个线程共享同一个对象。我已经用发行版和调试版对此进行了多次测试,每次结果都是正确的。为什么它仍然正确? 代码: 静态银行账户ThisbankAccount=新银行账户(10000); 公共货币 { 对于(int i=0;i=0) { m_余额-=amnt; } // } } 公共整数余额 { 收到 { 返回m_余额; } } 私人国际货币单位余额; } 仅仅因为某些东西现在能工作,并不意味着它能保证工作。比赛条件很难触发,可能需要数年时间才能浮出水面。当它

我想象结果会是负值,因为没有锁定并且多个线程共享同一个对象。我已经用发行版和调试版对此进行了多次测试,每次结果都是正确的。为什么它仍然正确? 代码:

静态银行账户ThisbankAccount=新银行账户(10000);
公共货币
{
对于(int i=0;i<1000;i++)
此银行账户。取款(25);
}
静态void Main(字符串[]参数)
{
线程client1=新线程(取款);
线程client2=新线程(取款);
线程client3=新线程(取款);
client1.Start();
client2.Start();
client3.Start();
client3.Join();
Console.WriteLine(ThisbankAccount.Balance);
Console.ReadLine();
}
}
公营银行帐户
{
object Acctlocker=新对象();
公共银行账户(初始金额)
{
m_余额=初始金额;
}
公款
{
//锁(Acctlocker)
//   {
如果(m_余额-amnt>=0)
{
m_余额-=amnt;
}
//  }
}
公共整数余额
{
收到
{
返回m_余额;
}
}
私人国际货币单位余额;
}

仅仅因为某些东西现在能工作,并不意味着它能保证工作。比赛条件很难触发,可能需要数年时间才能浮出水面。当它们出现时,很难追踪和诊断

要查看实际问题,请更改此代码:

if (m_balance - amnt >= 0)
{
    m_balance -= amnt;
}
致:

这引入了一个足够慢的代码路径,可以很容易地突出问题


您在当前代码中没有发现它的原因是您正在执行的操作(减法和比较)非常快。因此,这个窗口非常小——你很幸运,它不会发生。但是,在无限的时间内,它肯定会发生。

您的代码在没有同步的情况下工作的原因是,您的每个线程都在几微秒内完成,因此它们没有时间互相抢占并导致问题。它们开始、完成工作和结束的速度都很快,基本上是连续运行,而不是并行运行


为了查看由于缺少同步而导致的问题,您必须重写代码,使其在更长的时间段(毫秒级,而不是微秒级)内易受竞争条件的影响。因此,您需要使用更长的运行循环。

为什么您认为client1总是比client3结束得更快?你只是加入了客户3。你也应该加入其他人的行列,我并不特别了解C,但多线程编程的一个更棘手的方面是,你不能指望来自非同步程序的任何特定行为。您的三个线程分别尝试1000次取款。根据您的平台,可能需要数百万次取款才能发现问题。或者,也许在某个平台上,你永远看不到问题。或经验法则:你不能指望通过测试来发现线程错误。即使是单线程执行,你的代码也是不正确的。您正在从一个只有10000英镑的帐户中提取25000英镑。@mjwills Brain fart!每个线程都在运行一个循环,循环确实会运行一段时间。它肯定不会在几微秒内完成。@Servy我纠正了关于循环的部分。我仍然认为1000次迭代将在几微秒内运行。4GHz CPU每纳秒执行4个周期,每个周期执行多条指令。因此,可能甚至不到一微秒,因为所有东西都将在缓存中。
if (m_balance - amnt >= 0)
{
    m_balance -= amnt;
}
if (m_balance - amnt >= 0)
{
    Thread.Sleep(10);
    m_balance -= amnt;
}