Nano Hash - криптовалюты, майнинг, программирование

повысить эффективность параллельного доступа к словарю С#

У меня есть список, к которому обращаются несколько фоновых потоков для обновления/чтения. Действия по обновлению включают как вставки, так и удаления.

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

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

Из-за этого каждое чтение списка увеличивает потребление памяти моей службой.

Следует отметить, что вставки/удаления являются внутренними для класса, содержащего список. Но чтение предназначено для общественного потребления.

Мой вопрос:

Есть ли способ избежать клонирования списка и по-прежнему использовать его одновременно для чтения с использованием блокировок чтения/записи?

public class ServiceCache
    {
        private static List<Users> activeUsers;
        private static readonly object lockObject = new object();
        private static ServiceCache instance = new ServiceCache();

        public static ServiceCache Instance
        {
            get
            {
                return instance;
            }
        }

        private void AddUser(User newUser)
        {
            lock (lockObject)
            {
                //... add user logic
            }
        }

        private void RemoveUser(User currentUser)
        {
            lock (lockObject)
            {
                //... remove user logic
            }
        }

        public List<Users> ActiveUsers
        {
            get
            {
                lock (lockObject)
                {
                    //The cache returns deep copies of the users it holds, not links to the actual data.
                    return activeUsers.Select(au => au.DeepCopy()).ToList();
                }
            }
        }
    }

  • Если независимые потоки удаляются из своей глубокой копии списка, как обеспечить значимую синхронизацию их работы? 23.04.2012
  • Эрик, глубокая копия предназначена только для использования в качестве моментального снимка кеша во времени, и ее изменение не должно отражаться в фактическом кеше. 23.04.2012
  • Боковое примечание: чтобы свести к минимуму время ... Я делаю его глубокий клон: именно по этой причине существует корень всех зол фразы преждевременной оптимизации. Глубокое клонирование любого нетривиального объекта вряд ли будет быстрой операцией. Вы всегда должны измерять, чтобы понять, что на самом деле представляет собой ваша оптимизация. 24.04.2012

Ответы:


1

Похоже, вам нужно использовать класс ConcurrentDictionary и создать ключ для каждого из объектов Users, которые вы храните. Тогда это становится таким же простым для добавления/обновления пользователя:

_dictionary.AddOrUpdate("key", (k, v) =>
    {
        return newUser;
    }, (k, v) =>
    {
        return newUser;
    });

А затем для удаления вы должны сделать это:

 Users value = null;
_dictionary.TryRemove("key", out value);

Получить список людей также будет очень просто, так как вам просто нужно будет сделать:

return _dictionary.Values.Select(x => x.Value).ToList();

Который должен вернуть копию содержимого словаря в этот самый момент.

И пусть среда выполнения .NET позаботится о многопоточности за вас.

23.04.2012
  • На самом деле, вы можете просто вернуть .Values, что является копированием при чтении. 24.04.2012
  • Интересно, я этого не понимал! Теперь, когда я это прочитал, это имеет смысл =D 24.04.2012

  • 2

    Вы можете использовать блокировку чтения-записи, чтобы разрешить одновременное чтение.

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

    23.04.2012
  • Имеет ли значение, даже если блокировка является локальной для этого класса, но я получаю доступ к объекту, который он блокирует снаружи для чтения? 23.04.2012

  • 3

    Из-за этого каждое чтение списка увеличивает потребление памяти моей службой.

    Почему? Звонящие не выпускают ссылку? Им это необходимо, так как содержимое словаря может измениться.

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

    Пара других подходов:

    • Возвращайте одну и ту же копию всем вызывающим объектам до тех пор, пока коллекция не будет изменена. Возвращаемая коллекция должна быть неизменной

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

    23.04.2012
    Новые материалы

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

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..