【问题标题】:C# Creating global number which increase by 1C#创建增加1的全局数字
【发布时间】:2019-02-18 03:54:52
【问题描述】:

我正在编写简单的银行账户教程程序。对于每个注册的新客户,帐号将增加 1,以获得新的 ID。 我在“C# Mueller”一书中看到了例子。我只是好奇这是否是执行此操作的正确方法,它将如何处理并发注册?有没有更好的方法来处理这个问题,也许是单例或全局变量,内存缓存?在现实世界的应用程序中如何处理这样的项目?

public class BankAccount
{
    private static int _nextAccountNumber = 1000;
    private int _accountNumber;

    private double _balance;

    public void InitBankAccount()
    {
        _accountNumber = ++_nextAccountNumber;
        _balance = 0.0;
    }

    public void Deposit(decimal amount) 
    {
        _balance += amount;
    }
    etc...

这个网站也很有用:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement

【问题讨论】:

  • 您可以轻松测试并证明您的代码不可靠。即:Parallel.ForEach(Enumerable.Range(1, 1000), i => { new BankAccount().InitBankAccount(); }); Assert.AreEqual(2000, BankAccount._nextAccountNumber);。之后,您可以在自增操作上使用lock statement 来获得互斥。
  • 当您重新启动应用程序时,计数会重新开始。现实生活中的应用程序将生成的数字存储在数据库中

标签: c# .net-core asp.net-core-2.0


【解决方案1】:

您实际上可以在这里使用Interlocked.Increment,它返回增加的金额。它应该是线程安全的,文档链接中有一个示例用于此目的。

using System.Threading;

... 

public void InitBankAccount()
{
    _accountNumber = Interlocked.Increment(ref _nextAccountNumber);
    _balance = 0.0;
}

【讨论】:

    【解决方案2】:

    你在做什么是好的,但不是线程安全的。 thepirat000 在评论中提到您可以使用 lock 语句。

    private static object acctNumLock = new object();
    …
    lock(acctnumLock) { 
        _accountNumber = ++_nextAccountNumber;
        }
    

    您还应该考虑使用更有效的Interlock.Increment 方法。 lock 语句允许您“锁定”(一次只允许一个线程访问)到一个语句块。 Interlock.Increment 是一个原子操作,它只做一件事(即递增一个值),但这样做的方式是确保操作在线程切换之前完成。两者都提供线程安全。

    有没有更好的方法?这是一个非常难以回答的问题,因为这取决于您要做什么。我怀疑实际的银行应用程序会取出数据库锁并使用特定的算法来生成帐号(即一个更复杂的过程)。如果您只是想为简单的应用程序生成唯一值,那么您应该可以正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多