线程锁允许同时进行线程访问



我有一个助手类,它将被我的web应用程序的多个同时用户调用。这个类中的一个函数试图创建一个保证在数据库中唯一的字符串,即使50个不同的用户/线程同时调用该函数也是如此。以下是我的代码的重要部分:

private Object threadLock = new Object();
private string generateConfigIDThreadLock(Settings settings, string salesOrderNumber, string configModifiedOn) {
lock(threadLock) {
return generateConfigID(settings, salesOrderNumber, configModifiedOn);
}
}
private string generateConfigID(Settings settings, string salesOrderNumber, string configModifiedOn) {
string soTruncated = string.Empty;
if (salesOrderNumber.Length >= 5) {
soTruncated = salesOrderNumber.Substring(salesOrderNumber.Length - 5, 5);
} else {
soTruncated = salesOrderNumber;
}
int configModifiedOnSummed = Utilities.SumNumbers(configModifiedOn);
string newConfigID = $ "{soTruncated}-{DateTime.Now.Hour}{DateTime.Now.Minute}{DateTime.Now.Second}{DateTime.Now.Millisecond}-{configModifiedOnSummed}";
System.Threading.Thread.Sleep(50); // simulate the time for an API roundtrip
return newConfigID;
}

在我的测试装备中,我通过以下操作模拟大量同时使用:

static void Main(string[] args) {
int n = 50;
for (int i = 0; i < n; i++) {
Thread t = new Thread(TestOnMultipleThreads);
t.Start();
}
Console.ReadLine();
}
private static void TestOnMultipleThreads() {
var functions = new Functions();
string configID = functions.GetConfigID(string.Empty, "S-00018437", "2021-12-11 22:11:22");
if (configIDs.Contains(configID)) {
Console.WriteLine("PROLBEM! ConfigId was generated twice: " + configID);
} else {
Console.WriteLine("Unique configID: " + configID);
configIDs.Add(configID);
}
}

我不能使用guid来实现唯一性;我需要将字符串保持在25个字符以下,并在配置ID中使用SO#和时间戳的部分。请注意TestOnMultipleThreads()中的硬编码销售订单号和日期/时间戳;这是一个真实的场景。许多呼叫者可能具有相同的SO#和相同的日期时间。我需要使用销售订单#的元素和当前时间戳来生成唯一性。正如您所看到的,milsecs是我的唯一字符串的一部分,所以即使两个调用间隔1ms,结果字符串ID也将是唯一的。但在我的模拟中,我每次都会得到重复。这似乎意味着我的线程锁不起作用;如果是的话,并且由于我也使用Thread.Sleep(50),配置ID生成将不可能在同一个1ms内发生。

我做错了什么?为什么我得到重复?为什么线程阻塞没有按预期发生?

在您的代码中,看起来每个线程都在单独的Function实例上工作,因此它们都锁定在自己的(单独的(锁定对象上。

快速解决方案是将该对象设置为静态对象,以便在函数的所有实例之间共享,或者让所有线程共享函数的同一实例。

最新更新