public async Task AcquireLock() { MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString()); IAcquire acq = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(0)); Assert.IsTrue(acq.Acquired); }
public async Task Acquire_WaitUntilExpire_Acquire() { MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString()); IAcquire acq1 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(0)); Assert.IsTrue(acq1.Acquired); IAcquire acq2 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(0)); Assert.IsFalse(acq2.Acquired); await Task.Delay(TimeSpan.FromSeconds(10)); IAcquire acq3 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(0)); Assert.IsTrue(acq3.Acquired); }
public async Task Acquire_BlockFor5Secounds_Release_Acquire() { MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString()); IAcquire acq1 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0)); Assert.IsTrue(acq1.Acquired); IAcquire acq2 = await InTimeRange(() => mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5)), 4000, 6000); Assert.IsFalse(acq2.Acquired); await mongoLock.ReleaseAsync(acq1); IAcquire acq3 = await InTimeRange(() => mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(5)), 0, 1500); Assert.IsTrue(acq3.Acquired); }
public async Task Acquire_Block_Release_And_Acquire() { MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString()); IAcquire acq1 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0)); Assert.IsTrue(acq1.Acquired); IAcquire acq2 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0)); Assert.IsFalse(acq2.Acquired); await mongoLock.ReleaseAsync(acq1); IAcquire acq3 = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(0)); Assert.IsTrue(acq3.Acquired); }
// C# 7.1 requires for async Main static async Task Main(string[] args) { const string сonnectionString = "--mognodb connection string--"; MongoClient client = new MongoClient(сonnectionString); IMongoDatabase database = client.GetDatabase("sample"); // Regular collection, not a capped! IMongoCollection <LockAcquire <Guid> > locks = database.GetCollection <LockAcquire <Guid> >("locks"); // This collection should be a capped! https://docs.mongodb.com/manual/core/capped-collections/ // The size of the cappred collection should be enough to put all active locks. // One ReleaseSignal is about 32 bytes, so for 100,000 simultaneously locks, you need a capped collection size ~3 megabytes IMongoCollection <ReleaseSignal> signals = database.GetCollection <ReleaseSignal>("signals"); Guid lockId = Guid.Parse("BF431614-4FB0-4489-84AA-D3EFEEF6BE7E"); // Guid lockId is a name of your distributed lock. You can also use string, int, etc. MongoLock <Guid> mongoLock = new MongoLock <Guid>(locks, signals, lockId); // Try to acquire exclusve lock. Lifetime for created lock is 30 secounds IAcquire acquire = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(10)); try { if (acquire.Acquired) { // critical section, it cannot be executed by more than one thread on any server at a time // ... // ... } else { // Timeout! Maybe another thread did not release the lock... We can try again or throw excepton } } finally { // if (acquire.Acquired) no need to do it manually await mongoLock.ReleaseAsync(acquire); } }
public void Synchronize_CriticalSection_For_4_Threads() { MongoLock <string> mongoLock = new MongoLock <string>(Locks, Signals, Guid.NewGuid().ToString()); List <Task> tasks = new List <Task>(); List <int> bucket = new List <int>() { 0 }; Random random = new Random(DateTime.UtcNow.GetHashCode()); for (int i = 0; i < 4; i++) { tasks.Add(Task.Run(async delegate { for (int j = 0; j < 100; j++) { IAcquire acq = await mongoLock.AcquireAsync(TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(10)); try { int count = bucket.Count; Thread.Sleep(random.Next(0, 10)); int value = bucket[count - 1]; bucket.Add(value + 1); } finally { await mongoLock.ReleaseAsync(acq); } } })); } Task.WaitAll(tasks.ToArray()); Assert.IsTrue(bucket.SequenceEqual(Enumerable.Range(0, 401))); }