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
- Host: GitHub
- URL: https://github.com/soenneker/soenneker.asyncs.locks
- Owner: soenneker
- License: mit
- Created: 2025-12-20T12:28:41.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-05-29T00:53:40.000Z (20 days ago)
- Last Synced: 2026-05-29T02:24:29.805Z (20 days ago)
- Topics: async, asynclock, asyncs, csharp, dotnet, gate, initialization, locks, mutex, semaphore, semaphoreslim, util
- Language: C#
- Homepage: https://soenneker.com
- Size: 208 KB
- Stars: 1
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: .github/CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: .github/CODE_OF_CONDUCT.md
- Security: .github/SECURITY.md
Awesome Lists containing this project
README
[](https://www.nuget.org/packages/soenneker.asyncs.locks/)
[](https://github.com/soenneker/soenneker.asyncs.locks/actions/workflows/publish-package.yml)
[](https://www.nuget.org/packages/soenneker.asyncs.locks/)
[](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 |