Reputation: 418
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.
Upvotes: 0
Views: 7558
Reputation: 856
Here is a better example test for RedLock.Net. The timespans used are for my application. Every thread should eventually get the lock, but you can see the wait times between each thread acquiring the lock.
public static void Main() {
List<RedLockEndPoint> endPoints = [
new DnsEndPoint("localhost", 6379)
];
RedLockFactory redLockFactory = RedLockFactory.Create(endPoints);
Parallel.For(0, 10, x => {
TimeSpan expiry = TimeSpan.FromSeconds(120);
TimeSpan wait = TimeSpan.FromSeconds(60);
TimeSpan retry = TimeSpan.FromSeconds(5);
using IRedLock? redLock = redLockFactory.CreateLock("123456", expiry, wait, retry);
if (redLock.IsAcquired) {
Console.WriteLine($"User:{x} acquired lock at {DateTimeOffset.Now:dd-MM-yyyy HH:mm:ss}.");
Task.Delay(500 * x).GetAwaiter().GetResult();
}
else {
Console.WriteLine($"User:{x} didn't get the lock.");
}
});
}
Here is an example output:
User:0 acquired lock at 12-09-2024 13:22:28.
User:9 acquired lock at 12-09-2024 13:22:28.
User:6 acquired lock at 12-09-2024 13:22:34.
User:4 acquired lock at 12-09-2024 13:22:39.
User:8 acquired lock at 12-09-2024 13:22:44.
User:2 acquired lock at 12-09-2024 13:22:50.
User:1 acquired lock at 12-09-2024 13:22:55.
User:5 acquired lock at 12-09-2024 13:22:56.
User:7 acquired lock at 12-09-2024 13:23:01.
User:3 acquired lock at 12-09-2024 13:23:07.
Upvotes: 0
Reputation: 184
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:
using
block, releasing its lock (now another thread can win)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.
Upvotes: 4