多个线程但不锁定仍能提供正确的结果

时间:2017-08-02 13:40:45

标签: c# multithreading

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

   static BankAccount ThisbankAccount = new BankAccount(10000);
    public static void WithdrawMoney()
    {
        for(int i = 0; i < 1000; i++)
        ThisbankAccount.WithdrawMoney(25);
    }

    static void Main(string[] args)
    {
        Thread client1 = new Thread(WithdrawMoney);
        Thread client2 = new Thread(WithdrawMoney);
        Thread client3 = new Thread(WithdrawMoney);

        client1.Start();
        client2.Start();
        client3.Start();

        client3.Join();
        Console.WriteLine( ThisbankAccount.Balance);
        Console.ReadLine();
    }
}

public class BankAccount
{

    object Acctlocker = new object();

    public BankAccount(int initialAmount)
    {
        m_balance = initialAmount;
    }

    public void WithdrawMoney(int amnt)
    {
    //    lock(Acctlocker)
     //   {
            if (m_balance - amnt >= 0)
            {
                m_balance -= amnt;
            }
      //  }
    }

    public int Balance
    {
        get
        {
            return m_balance;
        }
    }

    private int m_balance;
}

2 个答案:

答案 0 :(得分:3)

仅仅因为某些作品现在并不意味着保证能够正常运作。种族条件难以触发,可能需要数年才能浮出水面。当它们浮出水面时,它们很难非常难以追踪和诊断。

要查看您的问题,请更改此代码:

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

为:

if (m_balance - amnt >= 0)
{
    Thread.Sleep(10);
    m_balance -= amnt;
}

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

您没有使用当前代码发现它的原因是您正在进行的操作(减法和比较)非常快。所以race condition的窗口非常小 - 你很幸运,它不会发生。但是,在无限的时间内,肯定会

答案 1 :(得分:0)

您的代码在没有同步的情况下工作的原因是您的每个线程都在几微秒内完成,因此他们没有时间相互抢先并导致问题。他们开始,完成他们的工作,并且如此迅速地完成,他们基本上是连续而不是并行运行。

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