Синхронизация в C#: аналог ключевого слова Java synchronized

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для обеспечения потокобезопасности операций в C# применяйте конструкцию lock с приватным объектом в качестве синхронизатора:

csharp
Скопировать код
private object _sync = new object();

public void SyncMethod()
{
    lock (_sync)
    {
        // Код, защищенный от одновременного выполнения в различных потоках
    }
}

Ключевое слово lock в C# выполняет ту же функцию, что и synchronized в Java, блокируя одновременный доступ к критическим областям кода.

Кинга Идем в IT: пошаговый план для смены профессии

Синхронизация на уровне метода

Для синхронизации всего метода в C# используйте атрибут [MethodImpl(MethodImplOptions.Synchronized)]:

csharp
Скопировать код
using System.Runtime.CompilerServices;

[MethodImpl(MethodImplOptions.Synchronized)]
public void SyncMethod()
{
    // Метод, защищенный от совместного доступа, аналогично синхронизированному методу в Java
}

Однако следует обращаться с этим механизмом аккуратно, поскольку он может вызывать замедление выполнения и ограничивает согласованность только на уровне метода.

Тонкая настройка синхронизации с помощью 'lock'

Конструкция lock предоставляет более гибкий контроль и дополнительную защиту, как на уровне всего метода, так и в его отдельных участках. Применяйте в тех случаях, когда это необходимо:

csharp
Скопировать код
public void PartialSyncMethod()
{
    // Обычные операции, предшествующие защищенному участку

    lock (_sync)
    {
        // Здесь происходит синхронизированная обработка данных
    }

    // Операции после синхронизированного участка кода
}

Визуализация

Представьте synchronized в Java как VIP-зону в аэропорту:

Java
Скопировать код
public synchronized void accessLounge() {
    // В VIP-зале может находиться только один человек за раз
}

Аналогия в C# — как строгий охранник перед клубом:

csharp
Скопировать код
private object bouncerList = new object();

lock (bouncerList) {
    // Под наблюдением охранника, в клуб может войти только один человек за раз
}

В обоих случаях ключевая идея в том, что обеспечивается эксклюзивный доступ к ресурсам:

Markdown
Скопировать код
Java `synchronized`: 🔒 – Один замок, один ключ, один путешественник.
C# `lock`: 💂 – Строгая система контроля, один охранник, единоличный доступ.

Эти инструменты гарантируют выполнение операций только одним потоком за раз, обеспечивая потокобезопасность в многопоточной среде.

Управление взаимодействием между потоками

Для управления сложными сценариями взаимодействия потоков в C# разработан класс Monitor, чьи методы Monitor.Wait и Monitor.Pulse позволяют координировать действия потоков:

csharp
Скопировать код
lock (_sync)
{
    // Ожидание сигнала к действию
    while (!greenSignal)
    {
        Monitor.Wait(_sync);
    }

    // Выполнение задач после получения сигнала

    // Оповещение остальных потоков о возможности действия
    Monitor.Pulse(_sync);
}

Эти инструменты позволяют точно контролировать порядок выполнения действий в потоках.

Избегайте подводных камней при синхронизации

Важно отметить, что при использовании lock необходимо избегать блокировки this и typeof(Foo) с целью предотвращения возможного взаимного блокирования с внешними вызывающими методами. Для блокировки более подходящим будет специальный объект-синхронизатор, такой как _sync.

Класс Interlocked в C# предназначен для потокобезопасного выполнения операций над примитивными типами данных с помощью атомарных операций.

Что происходит "за кулисами"

Внутри lock в C# используются методы Monitor.Enter и Monitor.Exit, что напоминает работу ключевого слова synchronized в Java. Для программистов, переходящих со Java на C#, будет приятно обнаружить знакомые концепты.

Полезные материалы