
В ноябре 2024 года с выходом .NET 9 и обновлением C# до версии 13 мы получили интересные нововведения, которые касаются типов данных и семантики блокировок. Каждый крупный релиз .NET сопровождается новыми инструментами, которые улучшают производительность, безопасность и удобство разработки. В C# 13 такой новинкой стал System.Threading.Lock. Это попытка сделать многопоточность чуть менее токсичной и чуть более предсказуемой.
Что не так со старым lock?
Традиционно в C# для обеспечения взаимного исключения потоков используется ключевое слово lock в сочетании с любым объектом (object). Однако такой подход может приводить к узким местам в производительности и потенциальным рискам взаимной блокировки (deadlock).
С выходом C# 13 и .NET 9 был представлен новый тип блокировки — System.Threading.Lock. Это специализированный механизм синхронизации, который улучшает управление многопоточностью, предоставляя более безопасный и производительный способ блокировки потоков.
Почему это важно?
Многопоточность — это всегда компромисс между производительностью и сложностью реализации. System.Threading.Lock предлагает два основных преимущества:
-
Исключение ошибок при выборе объекта для блокировки: использование специального типа блокировки вместо произвольных объектов уменьшает вероятность ошибок и улучшает контроль за синхронизацией.
-
Гибкость и контроль: с
System.Threading.Lockвы можете настроить тайм-ауты и отмену операций, избегая зависания потоков.
Кроме того, новая структура эффективнее работает в сценариях с высокой нагрузкой.
Основные сценарии применения
-
Приложения с высокими требованиями к производительности: в средах с высокой конкуренцией, где требуется частая блокировка и разблокировка,
System.Threading.Lockснижает издержки на переключение контекста. -
Сложные задачи синхронизации: для приложений, требующих тонкой настройки блокировок, новый тип блокировки предоставляет более гибкий API.
-
Избежание взаимоблокировок: новые возможности для управления блокировками, такие как тайм-ауты и отмена, значительно снижают вероятность возникновения взаимоблокировок.
Пример:
Ниже приведен System.Threading.Lockпример кода, демонстрирующий безопасное обновление общего ресурса в многопоточной среде:
using System; using System.Threading; using System.Threading.Tasks; public class Account { private decimal _balance; private Lock _balanceLock = new Lock(); public Account(decimal initialBalance) { _balance = initialBalance; } public void Debit(decimal amount) { if (amount <= 0) throw new ArgumentException("Amount must be positive", nameof(amount)); using (_balanceLock.EnterScope()) { if (_balance < amount) throw new InvalidOperationException("Insufficient funds"); _balance -= amount; } } public void Credit(decimal amount) { if (amount <= 0) throw new ArgumentException("Amount must be positive", nameof(amount)); using (_balanceLock.EnterScope()) { _balance += amount; } } public decimal GetBalance() { using (_balanceLock.EnterScope()) { return _balance; } } } public class Program { public static async Task Main() { var account = new Account(1000m); var tasks = new Task[10]; for (int i = 0; i < tasks.Length; i++) { tasks[i] = Task.Run(() => { for (int j = 0; j < 100; j++) { account.Credit(10); account.Debit(10); } }); } await Task.WhenAll(tasks); Console.WriteLine($"Final balance: {account.GetBalance()}"); } }
В приведенном коде:
-
Класс
Account: представляет банковский счёт, включает методы для списания, зачисления и получения баланса. -
Поле
_balanceLock: использует новый типLockизSystem.Threading, чтобы обеспечить потокобезопасный доступ к полю_balanceи избежать ошибок, связанных с выбором объекта для традиционногоlock. -
Метод
EnterScope(): применяется для входа в область блокировки, обеспечивая, что доступ к общему ресурсу будет безопасным и взаимно-исключающим, благодаря специализированному типу блокировки. -
Оператор
using: автоматизирует освобождение блокировки в конце области действия, предотвращая возникновение взаимоблокировок и упрощая управление блокировками.
Благодаря использованию нового типа System.Threading.Lock код обеспечивает более эффективную и гибкую синхронизацию потоков, снижая риски, связанные с производительностью и потенциальными проблемами, возникающими при использовании универсальных объектов для lock.
Реализация System.Threading.Lock основана на следующих ключевых концепциях:
-
Специализированный объект блокировки:
System.Threading.Lock— это тип, специально разработанный для синхронизации потоков, что позволяет избежать недостатков традиционного подхода с использованием произвольных объектов для блокировок. -
Управление областью действия: метод
EnterScope()обеспечивает вход в область блокировки, гарантируя потокобезопасный доступ к общим ресурсам. -
Автоматическое освобождение: использование оператора
usingпомогает автоматически освободить блокировку, предотвращая потенциальные взаимоблокировки и обеспечивая более чистое и безопасное управление синхронизацией.
ссылка на оригинал статьи https://habr.com/ru/articles/876380/
Добавить комментарий