Home > Enterprise >  Thread lock allows simultaneous thread access
Thread lock allows simultaneous thread access

Time:12-13

I have a helper class that will be called a lot from multiple simultaneous users of my webapp. One function in this class attempts to create a string that is guaranteed unique within the database, even if 50 different users/threads are making a call to the function at the same time. Here are the essential pieces of my code:

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;
}

In my test harness I am simulating heavy simultaneous usage by doing this:

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);
  }
}

I cannot use a guid to achieve uniqueness; I have a requirement to keep the string under 25 chars and to use portions of SO # and timestamp in the Config ID. Notice the hardcoded sales order number and date/time stamp in TestOnMultipleThreads(); this is a real scenario. Many callers could have the same SO # and that same datetime. I need to use elements of the Sales Order # and the current timestamp for generating uniqueness. As you can see, milsecs are part of my unique string, so even if 2 calls come 1 ms apart, the resulting string ID will be unique. But in my simulation, I get duplicates every time. This seems to mean my thread lock isn't working; if it were, and since I'm using Thread.Sleep(50) as well, there would be no possible way for Config ID generations to occur within the same 1 ms.

What am I doing wrong? Why am I getting duplicates? Why isn't thread blocking occurring as expected?

CodePudding user response:

In your code, it looks like each thread is working on a separate instance of Functions, so they are each locking on their own (separate) locking object.

The quick fix would be to make that object static so that it is shared across all instances of Functions, or have all threads share the same instance of Functions.

  • Related