控制台例子:
1. Nuget包管理器添加 StackExchange.Redis
说明: 单机的意思说Redis只存在于某一台服务器上,不考虑集群或者主从部署的情况
2.代码如下:
using StackExchange.Redis;
using System;
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost,password=000415");
IDatabase db = redis.GetDatabase();
//redis键名
string resource = "myResourceName";
//锁的令牌
string lockToken = Guid.NewGuid().ToString();
//过期时间
TimeSpan expiry = TimeSpan.FromSeconds(5);
//并发数
int ct = 500;
var tasks = new Task[ct];
for (int i = 0; i < ct; i++)
{
int client = (i + 1);
tasks[i] = Task.Run(async () =>
{
while (true)
{
//获得锁
if (await db.LockTakeAsync(resource, lockToken, expiry))
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端{client} 创建了锁 ********************************* ");
//开启异步线程,定时2秒延长锁
var cancellationTokenSource = new CancellationTokenSource();
var extendLockTask = Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromSeconds(2), cancellationTokenSource.Token);
bool extended = await db.LockExtendAsync(resource, lockToken, expiry);
if (extended)
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} --------------- 客户端{client} 已延长了锁 ---------------");
}
else
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}--------------- 客户端{client} 延长了锁失败!---------------");
break;
}
}
}, cancellationTokenSource.Token);
// 模拟偶发任务耗时
if ((client % 5) == 0)
{
await Task.Delay(5000); // 如果 client 是 5 的倍数,则延时 5 秒
}
else
{
await Task.Delay(60); // 否则延时 60 毫秒
}
//取消延长
cancellationTokenSource.Cancel();
try
{
await extendLockTask;
}
catch (OperationCanceledException)
{
//Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")}--------------- 客户端{client} 延长任务取消!---------------");
}
//释放锁
await db.LockReleaseAsync(resource, lockToken);
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss:fff")} ********************************* 客户端{client} 释放了锁 ********************************* ");
break;
}
else
{
// 获取锁失败以后随机等待一段时间后重试
int delayMilliseconds = new Random().Next(50, 500); // 随机生成一个等待时间
await Task.Delay(delayMilliseconds);
}
}
});
}
Task.WaitAll(tasks);
Task.WaitAll(tasks);
Console.WriteLine("按下回车键停止...");
Console.ReadLine();