以下帮助程序类线程是否安全?

Tom*_*Tom 3 c# thread-safety

我需要跟踪顺序Id,这是通过一个SP返回给我的,它在4个表中执行max(id),db中没有管理序列的标识符/序列.这显然会出现并发问题,所以我创建了一个帮助类来确保始终生成唯一的Id.

帮助程序通过其存储库初始化,该存储库最初调用DB以查找当前Id,所有后续的Id请求都通过帮助程序在内存中提供服务.只有一个应用程序使用DB(我的)所以我不需要担心其他人出现并创建交易并使Id不同步.我认为我已经获得了线程安全的基础知识,但我担心当助手初始化时的竞争条件,有人可以建议:)

private class TransactionIdProvider
{
private static readonly object Accesslock = new object();
private int _transactionId;
public int NextId
{
    get
    {
        lock (Accesslock)
        {
            if(!Initialised) throw new Exception("Must Initialise with id first!!");
            return _transactionId++;
        }
    }
}

public bool Initialised { get; private set; }

public void SetId(int id)
{
    lock (Accesslock)
    {
        if (Initialised) return;
        _transactionId = id;
        Initialised = true;
    }
}

public TransactionIdProvider()
{
    Initialised = false;
}
}
Run Code Online (Sandbox Code Playgroud)

辅助类在存储库中初始化:

private static readonly TransactionIdProvider IdProvider = new TransactionIdProvider();

    public int GetNextTransactionId()
    {
        if(!IdProvider.Initialised)
        {
            // Ask the DB
            int? id = _context.GetNextTransactionId().First();
            if (!id.HasValue)
                throw new Exception("No transaction Id returned");
            IdProvider.SetId(id.Value);
        }

        return IdProvider.NextId;
    }
Run Code Online (Sandbox Code Playgroud)

SLa*_*aks 8

它是线程安全的,但它不必要地慢.
你不需要锁来增加数字; 相反,你可以使用原子数学.

此外,您在所有实例(它static)之间共享锁定,这是不必要的.(一次运行两个不同的实例没有错)

最后,(恕我直言)有一个单独的未初始化状态是没有意义的.

我会这样写:

class TransactionIdProvider {
    private int nextId;
    public TransactionIdProvider(int id) {
        nextId = value;
    }

    public int GetId() {
        return Interlocked.Increment(ref nextId);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1因为您的代码更简洁,更易读.但速度差异似乎无关紧要. (3认同)