我需要跟踪顺序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)
它是线程安全的,但它不必要地慢.
你不需要锁来增加数字; 相反,你可以使用原子数学.
此外,您在所有实例(它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)
| 归档时间: |
|
| 查看次数: |
596 次 |
| 最近记录: |