0

I want to use Redis for distributed lock. I'm using RedLock.net nuget package for this. But thread is able to acquire the lock, even another thread is already acquired the lock.

Here is sample code:

public void Demo(RedLockFactory redLockFactory)
        {
            Parallel.For(0, 5, x =>
            {
                TimeSpan expiry = TimeSpan.FromSeconds(30);
                var wait = TimeSpan.FromSeconds(10);
                var retry = TimeSpan.FromSeconds(1);

                string user = $"User:{x}";
                using (var redLock = redLockFactory.CreateLock(resource, expiry, wait, retry))
                {

                    // make sure we got the lock
                    if (redLock.IsAcquired)
                    {
                        Console.WriteLine($"{user} acquired lock at {DateTimeOffset.Now.ToString("dd-MM-yyyy HH:mm:ss")}.");
                    }
                    else
                    {
                        Console.WriteLine($"{user} didn't get the lock.");
                    }
                }
            });
        }

This is output of my demo

User:4 acquired lock at 06-10-2020 09:24:34.
User:2 acquired lock at 06-10-2020 09:24:34.
User:1 acquired lock at 06-10-2020 09:24:34.
User:0 acquired lock at 06-10-2020 09:24:35.
User:3 acquired lock at 06-10-2020 09:24:35.

As you can see, every thread is able to acquire the lock, which should not happen.

Once lock is acquired then other thread should not able to acquire the lock.

Programmer
  • 398
  • 1
  • 9
  • 33

1 Answers1

4

Per RedLock.net/README.md, "the lock is automatically released at the end of the using block".

So I think what's happening in your demo output is:

  1. Five threads start in parallel, each attempting a lock on the same resource.
  2. Thread 4 wins (successfully acquires its lock) and does the following; meanwhile, the other threads wait (up to 10 seconds):
    • writes "acquired lock" to the console
    • passes out of the using block, releasing its lock (now another thread can win)
  3. Thread 2 wins and does the same while the remaining threads wait.
  4. Ditto for threads 1, 0, and 3.
  5. Each thread does its work quickly, so no thread fails to acquire a lock within 10 seconds.

If you want to see lock acquisition fail, do a very slow operation (>10 seconds) before exiting the using block. For demo purposes, you could Thread.Sleep(15000) after writing the "acquired" line.

Kyle Rogers
  • 184
  • 4
  • Then I think, It doesn't fulfill the definition of distributed lock. What if I have multiple instance of my application, Then All thread will be able to acquire the lock simultaneously. – Programmer Oct 06 '20 at 09:28
  • Only one thread at a time successfully gets a lock on the resource. In your demo, the threads happen to all be local, but you would see the same behavior if the threads were distributed across multiple instances. – Kyle Rogers Oct 06 '20 at 12:05
  • 1
    More info:When you call CreateLock, a lock is obtained from a quorum of the group of Redis servers. (see [Start() in RedLock.cs](https://github.com/samcook/RedLock.net/blob/6d789f0eb0dc9a7396ec63e66920c2335e2c80fc/RedLockNet.SERedis/RedLock.cs#L138)) When exiting the using block, C# calls `redLock.Dispose()`, and the lock is released across the Redis servers. (see [Dispose() in RedLock.cs](https://github.com/samcook/RedLock.net/blob/6d789f0eb0dc9a7396ec63e66920c2335e2c80fc/RedLockNet.SERedis/RedLock.cs#L604)) – Kyle Rogers Oct 06 '20 at 12:14