线程锁允许同时线程访问

Thread lock allows simultaneous thread access

我有一个助手 class,我的 web 应用程序的多个同时用户会经常调用它。此 class 中的一个函数尝试创建一个在数据库中保证唯一的字符串,即使有 50 个不同的 users/threads 同时调用该函数。以下是我的代码的基本部分:

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() 中的硬编码销售订单号和 date/time 戳记;这是一个真实的场景。许多呼叫者可能具有相同的 SO # 和相同的日期时间。我需要使用销售订单 # 的元素和当前时间戳来生成唯一性。如您所见,milsecs 是我唯一字符串的一部分,因此即使 2 次调用相隔 1 毫秒,生成的字符串 ID 也将是唯一的。但是在我的模拟中,我每次都会得到重复项。这似乎意味着我的线程锁不起作用;如果是的话,并且由于我也在使用 Thread.Sleep(50),因此不可能在相同的 1 毫秒内生成配置 ID。

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

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

快速解决方法是将该对象设为静态,以便它在所有 Functions 实例之间共享,或者让所有线程共享同一个 Functions 实例。