Потокобезопасное изменение глобальных конфигураций в многопоточном приложении

Monitor нельзя удерживать через await: продолжение может попасть на другой поток. Кроме того, три отдельные записи свойств позволяют читателю увидеть смешанную конфигурацию.

Короткий ответ

Что ответить на собеседовании

Monitor нельзя удерживать через await: продолжение может попасть на другой поток. Кроме того, три отдельные записи свойств позволяют читателю увидеть смешанную конфигурацию.

Подробный разбор

Ответ с пояснениями

Условие

В каких ситуациях данный код может приводить к ошибкам и какие подходы помогут устранить эти проблемы?

class SettingsManager
    {
        public static string ServiceUrl { get; private set; }
        public static string ServiceUser { get; private set; }
        public static string ServicePassword { get; private set; }

        private static object syncRoot = new object();

        public static async Task RefreshSettings(string configPath)
        {
            try
            {
                Monitor.Enter(syncRoot);

                var lines = await File.ReadAllLinesAsync(configPath);

                ServiceUrl = lines[0];
                ServiceUser = lines[1];
                ServicePassword = lines[2];
            }
            finally
            {
                Monitor.Exit(syncRoot);
            }
        }
    }

Ответ

Monitor нельзя удерживать через await: продолжение может попасть на другой поток. Кроме того, три отдельные записи свойств позволяют читателю увидеть смешанную конфигурацию.

Для сериализации обновлений используйте SemaphoreSlim.WaitAsync с Release в finally. Прочитайте файл, проверьте число строк и значения, затем создайте неизменяемый объект Settings и атомарно опубликуйте одну ссылку через Interlocked.Exchange.

Читатель должен один раз получить снимок через Volatile.Read и брать все поля из него, иначе даже отдельные корректные геттеры могут относиться к разным версиям. Не публикуйте частичные данные при ошибке чтения; сохраняйте предыдущий снимок. Пароль нельзя писать в логи. В исходнике Monitor.Exit также опасен, если Enter не успел успешно захватить блокировку.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее