Concurrent Collections: `ConcurrentDictionary` vs `Lock` (.NET 9)
1Concept
`ConcurrentDictionary<TKey, TValue>` provides lock-striped thread-safe operations. .NET 9 introduces the dedicated `System.Threading.Lock` object, which achieves higher performance than `Monitor` (`lock(object)`).
2Architecture Diagram
Legacy: lock(object) ──> Enters CLR Monitor syncblock .NET 9: lock(new System.Threading.Lock()) ──> Modern fast-path lightweight lock!
3Code Example
C# 13 & .NET 9
using System;
using System.Collections.Concurrent;
using System.Threading;
public class ConcurrencyCollectionDemo
{
public static void Main()
{
var concurrentCache = new ConcurrentDictionary<string, int>();
// GetOrAdd is atomic and lock-striped
int count = concurrentCache.GetOrAdd("active_sessions", key => 1);
Console.WriteLine($"Session Count: {count}");
// .NET 9 Dedicated Lock Primitive
System.Threading.Lock modernLock = new();
lock (modernLock)
{
Console.WriteLine("Executing critical section inside .NET 9 Lock primitive.");
}
}
}4Expected Output
Session Count: 1 Executing critical section inside .NET 9 Lock primitive.
5Key Takeaways
- ✓Use `ConcurrentDictionary` for shared multi-threaded read/write caches.
- ✓In .NET 9, use `System.Threading.Lock` instead of dummy `object _lock = new()` instances.
- ✓Be careful with factories in `GetOrAdd`: factory delegates may execute multiple times under race conditions.