以下函数的目的是创建存储数字序列和usedId的IdentityStore对象。一旦我们达到行的最大尺寸,它将删除集合并从0开始重新创建它。我需要此操作以原子方式工作,因为数字序列必须是唯一的。目前它不起作用。我可以采取什么方法来锁定每个呼叫的此功能。
可以有多个服务器,并且将运行多个实例。这只会锁定单个实例并且多个服务器之间存在竞争条件。如何在多个实例/机器上锁定它。
编辑:
我现在明白,我需要使用Mutex,以便线程能够跨应用程序的多个实例使用此代码块。如果Mutex不存在,请使用现有的互斥锁。这个实现是否正确?我使用了多线程单元测试,目前正在通过。但我不确定代码块是否会在互斥锁中正确执行。在阅读了关于此主题的MSDM文件后,我基于此实现
https://msdn.microsoft.com/en-us/library/bwe34f1k(v=vs.90).aspx
private int _sequence = 0;
private long _lastgen = -1;
private MongoDBRepository<IdentityStore> _mongoDBRepository;
public MongoIdGenerator(string mongoConnectionString)
{
_mongoDBRepository = new MongoDBRepository<IdentityStore>(mongoConnectionString);
}
public string GetIdForKey(string key, int maxSize)
{
var requestInitialOwnership = true;
bool mutexWasCreated;
Mutex m = new Mutex(
requestInitialOwnership,
"MyMutex",
out mutexWasCreated);
// This thread owns the mutex only if it both requested
// initial ownership and created the named mutex. Otherwise,
// it can request the named mutex by calling WaitOne.
if (!(requestInitialOwnership && mutexWasCreated))
{
m.WaitOne();
}
// Once the process has gained control of the named mutex,
// Hold onto it until the mongo record has been successfully created.
var collection = _mongoDBRepository.Collection;
IdentityStore idStore = new IdentityStore();
idStore.key = string.Empty;
if (_lastgen != -1)
{
idStore = collection.AsQueryable().OrderByDescending(i => i.usedId).FirstOrDefault();
if (_sequence < maxSize && idStore != null)
{
var arrayOfDigits = _sequence.ToString().Select(digit => int.Parse(digit.ToString()));
var _sequenceOfNumbers = _sequence.ToString().PadLeft((10 - arrayOfDigits.Count()), '0');
idStore.key = _sequenceOfNumbers;
idStore.usedId = _sequence;
_sequence++;
}
else
{
collection.Database.DropCollection(collection.CollectionNamespace.CollectionName);
_sequence = 0;
_lastgen = 0;
idStore.key = "000000000";
idStore.usedId = _sequence;
_sequence++;
}
}
else
{
_sequence = 0;
_lastgen = 0;
idStore.key = "000000000";
idStore.usedId = _sequence;
_sequence++;
}
unchecked
{
collection.InsertOne(idStore);
// Call ReleaseMutex to allow other threads to gain control
// of the named mutex. If you keep a reference to the local
// Mutex, you can call WaitOne to request control of the
// named mutex.
m.ReleaseMutex();
return idStore.key;
}