C# Creating global number which increase by 1

2019-08-16 02:01发布

问题:

I am writing simple bank account tutorial program. For each new customer which enrolls, the account number will be incremented by 1, for a new id. I saw example in "C# Mueller" book. I am just curious if this is proper way to conduct this, how will it handle concurrency enrollments? Is there a better to handle this, maybe with Singletons or global variables, memory cache? How would item like this be handled in real world application?

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...

This site is also useful: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement

回答1:

What you are doing is ok, but not thread safe. thepirat000 mentioned in a comment that you could use a lock statement.

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

You should also consider using the Interlock.Increment method which is more efficient. The lock statement allows you to 'lock' (allow only one thread access at a time) to a block of statements. The Interlock.Increment is an atomic operation, that only does one thing (namely increment a value), but does so in a way that ensures the operation is completed before the thread switches. Both provide thread safety.

Is there a better way? That's a very difficult question to answer because it depends on what you are trying to do. I suspect that actual banking applications take out DB locks and use specific algorithms to generate account numbers (i.e. a much more complicated process). If you are just trying to generate unique values for simple applications what you have should work fine.



回答2:

You can actually use Interlocked.Increment here, which returns the incremented amount. It should be thread safe, there's an example in the docs link that uses it for that purpose.

using System.Threading;

... 

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