Что произойдет, если несколько потоков (Thread) обратятся к общим (shared) полям без синхронизации?

«Что произойдет, если несколько потоков (Thread) обратятся к общим (shared) полям без синхронизации?» — вопрос из категории Многопоточность, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Без должной синхронизации произойдет состояние гонки (race condition), приводящее к неопределенному поведению, повреждению данных и трудноотлавливаемым багам.

Конкретные проблемы:

  1. Частичная запись (Tearing): Для полей размером больше машинного слова (например, double, decimal, DateTime) один поток может читать значение, которое другой поток записывает лишь частично, получая «битый» результат.
  2. Неверные вычисления: Операции инкремента (i++) не атомарны. Они выполняются как «чтение-изменение-запись». Потоки могут перезаписать результаты друг друга.
  3. Нарушение инвариантов: Если два поля логически связаны (например, X и Y координаты), один поток может увидеть новое значение X и старое значение Y.

Пример состояния гонки:

public class UnsafeCounter
{
    public int Count = 0; // Публичное поле — опасно!
}

var counter = new UnsafeCounter();
var tasks = new Task[1000];

for (int i = 0; i < tasks.Length; i++)
{
    tasks[i] = Task.Run(() => counter.Count++); // НЕБЕЗОПАСНО!
}
await Task.WhenAll(tasks);

Console.WriteLine(counter.Count); // Результат будет СЛУЧАЙНЫМ, меньше 1000

Способы синхронизации в C#:

  • lock (мьютекс): Базовый и самый распространенный способ.
    private readonly object _syncRoot = new object();
    lock (_syncRoot) { counter.Count++; }
  • Interlocked: Для простых атомарных операций (инкремент, сложение, обмен). Самый быстрый.
    Interlocked.Increment(ref counter.Count);
  • SemaphoreSlim, ReaderWriterLockSlim: Для более сложных сценариев доступа.
  • Потокобезопасные коллекции (ConcurrentBag, ConcurrentDictionary): Встроенная синхронизация.
  • Неизменяемые (immutable) типы: Самый безопасный подход — не использовать общее изменяемое состояние.