An open API service indexing awesome lists of open source software.

https://github.com/soenneker/soenneker.asyncs.locks

The fastest .NET async lock
https://github.com/soenneker/soenneker.asyncs.locks

async asynclock asyncs csharp dotnet gate initialization locks mutex semaphore semaphoreslim util

Last synced: 12 days ago
JSON representation

The fastest .NET async lock

Awesome Lists containing this project

README

          

[![](https://img.shields.io/nuget/v/soenneker.asyncs.locks.svg?style=for-the-badge)](https://www.nuget.org/packages/soenneker.asyncs.locks/)
[![](https://img.shields.io/github/actions/workflow/status/soenneker/soenneker.asyncs.locks/publish-package.yml?style=for-the-badge)](https://github.com/soenneker/soenneker.asyncs.locks/actions/workflows/publish-package.yml)
[![](https://img.shields.io/nuget/dt/soenneker.asyncs.locks.svg?style=for-the-badge)](https://www.nuget.org/packages/soenneker.asyncs.locks/)
[![](https://img.shields.io/github/actions/workflow/status/soenneker/soenneker.asyncs.locks/codeql.yml?label=CodeQL&style=for-the-badge)](https://github.com/soenneker/soenneker.asyncs.locks/actions/workflows/codeql.yml)

# Soenneker.Asyncs.Locks
### The fastest .NET async lock

This library provides a single primitive: `AsyncLock`.

### Design goal

`AsyncLock` is built to be the **fastest possible correct mutex** for real-world .NET systems.

It provides the following guarantees:

#### Cancellation-safe

- Fully supports cancellation before acquisition and while waiting for both async and sync callers.
- Cancelled waiters are removed immediately, never resumed, and never leaked � with **zero impact on the fast path**.

#### Unified async + sync locking

- Async and synchronous callers share the *same mutex*.
- Ordering is preserved without adapters, wrappers, or duplicated synchronization primitives.

#### Performance (by design)

- Uncontended acquisition is as close to a single atomic operation as possible
- No allocations, tasks, or state machines unless contention occurs
- Cancellation and disposal logic are completely excluded from the fast path
- Deterministic behavior under contention

---

## Installation

```bash
dotnet add package Soenneker.Asyncs.Locks
```

---

## Usage

### Async

```csharp
await using (await _lock.Lock(ct))
{
// critical section
}
```

### Sync

```csharp
using (_lock.LockSync())
{
// critical section
}
```

### Try-lock

```csharp
if (_lock.TryLock(out var releaser))
{
using (releaser)
{
// critical section
}
}
```

---

## Benchmarks

### Async lock acquisition

| Method | Mean | Error | StdDev | Median | Ratio | Allocated |
| ------------------------- | -------: | -------: | -------: | -------: | -----------: | --------: |
| **Soenneker.Asyncs.Lock** | 10.06 ns | 0.212 ns | 0.393 ns | 10.01 ns | baseline | - |
| SemaphoreSlim | 19.17 ns | 0.406 ns | 0.360 ns | 19.10 ns | 1.91x slower | - |
| Nito.AsyncEx.AsyncLock | 55.32 ns | 1.078 ns | 2.645 ns | 54.81 ns | 5.51x slower | 320 B |

---

### Synchronous lock acquisition

| Method | Mean | Error | StdDev | Median | Ratio | Allocated |
| ------------------------- | -------: | -------: | -------: | -------: | -----------: | --------: |
| **Soenneker.Asyncs.Lock** | 8.09 ns | 0.179 ns | 0.314 ns | 8.03 ns | baseline | - |
| SemaphoreSlim | 19.49 ns | 0.403 ns | 0.727 ns | 19.09 ns | 2.41x slower | - |
| Nito.AsyncEx.AsyncLock | 48.43 ns | 1.005 ns | 2.915 ns | 48.05 ns | 6.00x slower | 320 B |