The traditional lock statement used Monitor.Enter and Monitor.Exit for synchronization, which worked well but had limitations. It couldn't be used with using statements for more flexible scope control, and its implementation had room for performance improvements.
The .NET 9 runtime adds System.Threading.Lock, a dedicated lock type, and C# 13.0 teaches the lock statement to recognize it. Locking on a Lock uses its faster API instead of Monitor, and EnterScope() integrates with using for manual lock management.
Code
csharp
using System.Threading;
class BankAccount
{
private readonly Lock _balanceLock = new();
private decimal _balance;
public void Deposit(decimal amount)
{
lock (_balanceLock)
{
_balance += amount;
}
}
// Can also use with using for manual control
public void Transfer(decimal amount)
{
using (_balanceLock.EnterScope())
{
_balance -= amount;
// Lock automatically released when scope exits
}
}
}csharp
class BankAccount
{
private readonly object _balanceLock = new();
private decimal _balance;
public void Deposit(decimal amount)
{
lock (_balanceLock)
{
_balance += amount;
}
}
// Manual Monitor usage for complex scenarios
public void Transfer(decimal amount)
{
bool lockTaken = false;
try
{
Monitor.Enter(_balanceLock, ref lockTaken);
_balance -= amount;
}
finally
{
if (lockTaken)
Monitor.Exit(_balanceLock);
}
}
}Notes
- The new
Locktype is specifically designed for high-performance locking scenarios - Using
lockwith aLockobject uses its optimizedEnterScope()method instead ofMonitor EnterScope()returns a disposableScopestruct that releases the lock when disposed- The
Lockobject provides better performance thanMonitorin many scenarios - Traditional
lockstatements with other object types (likeobject,string) continue to useMonitor - Converting a
Locktoobjector another type falls back toMonitor-based locking; the compiler warns about this (CS9216) - Prefer
Lockfor new code; existing code usingobjectlocks continues to work unchanged