C# 13: Introducing System.Threading.Lock
Introduction
With every new release, C# keeps evolving to offer better performance, cleaner syntax, and safer abstractions. One of the more low-key — but genuinely interesting — additions in C# 13 is the introduction of a new synchronization primitive: System.Threading.Lock. Yes, we’ve all used the classic lock(obj) pattern for years, and while it’s been reliable, it’s also shown its age. Enter the new Lock
type — a lightweight, safer, and more ergonomic way to handle locking in multi-threaded code.
Let’s break it down.
The old way
Before .NET 9, if you wanted to protect a section of code from concurrent access, you’d do something like this:
It works, but it’s not always ideal. The old pattern relies on an object and runtime magic — and while that’s okay for most scenarios, it doesn’t give us a lot of control or transparency. Also, when you start mixing with async code or Span-based scenarios, things get tricky fast.
What’s new in C# 13?
The runtime in .NET 9 introduces a brand-new System.Threading.Lock type. It’s a ref struct, meaning it’s stack-only, allocation-free, and built for performance. Even better: C# 13’s lock
statement has been updated to support this new type directly. Here’s what it looks like:
Behind the scenes, the compiler transforms this into a call to _lock.EnterScope(), which returns a disposable struct. When the scope exits, the lock is automatically released. Neat, right?
The new Lock in C# 13 is a stack-allocated, safer, and more explicit synchronization primitive that integrates seamlessly with scoped using patterns for efficient and predictable locking. Example:
This is one of those features that won’t immediately change how everyone writes code — but for those of us who care about performance and clean synchronization, it’s a big win.
As always — happy coding! 😊