Skip to content

How to use StripedAsyncKeyedLocker

Mark Cilia Vincenti edited this page Nov 10, 2024 · 3 revisions

You need to start off with creating an instance of StripedAsyncKeyedLocker<T>. These methods allow for multiple optional parameters to set the number of stripes (defaults to 4049), the maximum number of requests for the semaphore that can be granted concurrently (defaults to 1) and an IEqualityComparer comparer.

Dependency injection

services.AddSingleton<StripedAsyncKeyedLocker<string>>();

Variable instantiation

var stripedAsyncKeyedLocker = new StripedAsyncKeyedLocker<string>();

Locking

// without cancellation token
using (await stripedAsyncKeyedLocker.LockAsync(myObject))
{
	...
}

// with cancellation token
using (await stripedAsyncKeyedLocker.LockAsync(myObject, cancellationToken))
{
	...
}

You can also use timeouts with LockOrNull / LockOrNullAsync methods to set the maximum time to wait, either in milliseconds or as a TimeSpan.

In the case you need to use timeouts to instead give up if unable to obtain a lock by a certain amount of time, you can also use TryLockAsync methods which will call a Func<Task> or Action if the timeout is not expired, whilst returning a boolean representing whether or not it waited successfully.

There are also synchronous Lock and TryLock methods available.

If you would like to check whether any request is using a specific key:

bool isInUse = asyncKeyedLocker.IsInUse(myObject);

Please note that, unlike with AsyncKeyedLocker, StripedAsyncKeyedLocker may incorrectly tell you that a key is in use when it isn't; this could happen when there is a collision between the key that you're checking and another key that's currently in use. A value of true therefore means that a lock would have to wait (assuming a MaxCount of 1); a value of false means that the key is definitely not currently in use.

Conditional locking

There are also overloaded methods called ConditionalLock and ConditionalLockAsync that accept a boolean parameter which, when set to false, will not do any locking. This can be useful either if you have a setting for enabling/disabling locking, or if you are using recursion given that the locks are not inherently reentrant.

double factorial = Factorial(number);

public static double Factorial(int number, bool isFirst = true)
{
  using (await stripedAsyncKeyedLocker.ConditionalLockAsync("test123", isFirst))
  {
    if (number == 0)
      return 1;
    return number * Factorial(number-1, false);
  }
}