Neu in .NET 9.0 [10]: Neue Klasse fĂĽr lock-Statements in C# 13.0
C# 13.0 führt die neue Klasse Lock ein, um Codeblöcke vor dem Zugriff durch weitere Threads zu sperren.
(Bild: Pincasso/Shutterstock)
- Dr. Holger Schwichtenberg
Ab .NET 9.0/C# 13.0 gibt es für das Sperren von Codeblöcken vor dem Zugriff durch weitere Threads die neue Klasse System.Threading.Lock, die man nun im Standard in Verbindung mit dem lock-Statement in C# verwenden sollte, "for best performance" wie Microsoft in der Dokumentation schreibt.
Videos by heise
Folgender Code aus der C#-Dokumentation auf Microsoft Learn zeigt ein Beispiel mit dem SchlĂĽsselwort lock und der Klasse System.Threading.Lock:
using System;
using System.Threading.Tasks;
namespace NET9_Console.CS13;
public class Account
{
// Vor .NET 9.0/C# 13.0 wurde hier System.Object verwendet statt
// System.Threading.Lock
private readonly System.Threading.Lock _balanceLock = new();
private decimal _balance;
public Account(decimal initialBalance) => _balance = initialBalance;
public decimal Debit(decimal amount)
{
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "The debit amount cannot be negative.");
}
decimal appliedAmount = 0;
lock (_balanceLock)
{
if (_balance >= amount)
{
_balance -= amount;
appliedAmount = amount;
}
}
return appliedAmount;
}
public void Credit(decimal amount)
{
if (amount < 0)
{
throw new ArgumentOutOfRangeException(nameof(amount), "The credit amount cannot be negative.");
}
lock (_balanceLock)
{
_balance += amount;
}
}
public decimal GetBalance()
{
lock (_balanceLock)
{
return _balance;
}
}
}
class AccountTest
{
static async Task Main()
{
var account = new Account(1000);
var tasks = new Task[100];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Run(() => Update(account));
}
await Task.WhenAll(tasks);
Console.WriteLine($"Account's balance is {account.GetBalance()}");
// Output:
// Account's balance is 2000
}
static void Update(Account account)
{
decimal[] amounts = [0, 2, -3, 6, -2, -1, 8, -5, 11, -6];
foreach (var amount in amounts)
{
if (amount >= 0)
{
account.Credit(amount);
}
else
{
account.Debit(Math.Abs(amount));
}
}
}
}
Der C#-13.0-Compiler generiert dann aus
lock (_balanceLock)
{
_balance += amount;
}
einen Aufruf der EnterScope()-Methode in der Klasse System.Threading.Lock:
using (balanceLock.EnterScope())
{
_balance += amount;
}
(rme)