AsyncSemaphore is a utility type that helps limit the number of concurrent usages of a given resource. eg. limit the number of concurrent requests to a database.

This is especially useful for actor systems, where a cold-start of a system might bring thousands of actors back to life. If you were to allow all these actors to individually request a database, the database could easily become overloaded.

Using a semaphore for this is one way to deal with this problem.

Example code using Redis

var maxConcurrency = 10;
var semaphore = new AsyncSemaphore(maxConcurrency);
var multiplexer = ConnectionMultiplexer.Connect("localhost:6379");
var db = multiplexer.GetDatabase();

// ...
// code that concurrently reads from redis 
// this might be inside a component called from within an actor
// ..or any other concurrent data flow
var res = 
    await semaphore.WaitAsync( async () => 
        //we are guaranteed to have max `maxConcurrency` concurrent calls here
        await db.StringGetAsync("some key"));

WARNING The AsyncSemaphore only guards concurrency inside a single process. If your system uses scale-out, the semaphore will only guard calls within the process on each instance.

Related: For other approaches to deal with similar problems, see Collective reads and writes