C# параллелизм, блокировка и объекты словаря

У меня есть несколько сущностей БД, которые загружаются в объекты БД. Один и тот же объект БД может быть загружен в несколько объектов БД. Периодически объект БД требует специальной обработки. Эта обработка должна выполняться одним потоком за раз. Блокировка здесь в порядке.

Обновлено: Важное примечание: процесс вызывает медленную веб-службу. Это то, что я пытаюсь предотвратить. Я не понимаю, как это можно сделать безопасно без замков.

Поэтому я создаю объект «замок», на который будут ссылаться объекты БД для блокировки. Объект висячего замка основан на сущности, поэтому два или более объекта БД для одной и той же сущности будут использовать один и тот же объект висячего замка. Я сохраняю эти замки в объекте словаря, используя идентификатор объекта БД в качестве ключа. Объект замка - это тоже простой строковый объект. Это правильный подход? Я думаю, я либо переусердствовал с разработкой, либо упрощаю это. Если подход правильный, как выглядит этот код? Работает, но под нагрузкой еще не тестировал.

Спасибо :)

public static func(CustomObject o)
{
    if (ReadyForUpdate(o))
    {
        lock (LookupPadLockByID(object.ID)
        {
            if (ReadyForUpdate(o))
            {
                PerformUpdate(object);
            }
        }
    }
}

private static readonly object padlockLock = new object();
private static readonly Dictionary<int, string> padLocks = new Dictionary<int,string>();
private static object LookupPadLockByID(int uniqueID)
{
    lock (padlockLock)
    {
        if (!padLocks.ContainsKey(uniqueID))
        {
            padLocks.Add(uniqueID, uniqueID + " is locked");
        }
    }

    return padLocks[uniqueID];
}

Метод PeformUpdate вызывает очень медленную веб-службу, а затем выполняет обновление БД. Это то, что мне нужно для предотвращения параллелизма.

Mikieeee 14.01.2009 01:26
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
5 746
4

Ответы 4

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

  • похоже, вы не снимаете блокировки с padLocks - это проблема?
  • вы получаете доступ к словарю вне padlockLock; return должен быть внутри lock

Для этой секунды это было бы проще:

object itemLock;
if (!padLocks.TryGetValue(uniqueID, out itemLock)) {
    itemLock = new object();
    padLocks.Add(uniqueID, itemLock);
}
return itemLock;

Если этот код является достаточно локальным (т.е. ваши объекты еще не экранированы), вы можете просто lock самой записи? Намного проще ...

Мне нужно изучить эту интернированность строк. Вы не единственный, кто на это указывает.

Mikieeee 14.01.2009 01:38

Я думаю, что вы слишком сильно разбираетесь в технике. Если вам нужно защитить только свои сущности БД (которые, как я предполагаю, представлены в вашем коде как «объект», который я заменю на «сущность»), вы можете просто использовать его в качестве блокировки. В качестве блокировки можно использовать любой ссылочный объект:

public static func(CustomObject o)
{
    if (ReadyForUpdate(o))
    {
        lock (entity)
        {
                if (ReadyForUpdate(o))
                {
                        PerformUpdate(entity);
                }
        }
    }
}

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

Mikieeee 14.01.2009 01:35

Если вы используете стандартную базу данных любого типа, я бы предложил полностью сбросить эти блокировки на стороне клиента в пользу транзакций и блокировок таблиц / строк.

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

Mikieeee 14.01.2009 01:23

Почему вы используете веб-службу для доступа к базе данных, когда знаете, что у вас будут транзакционные обновления данных?

Robert C. Barth 14.01.2009 02:01

Вызов веб-службы получает данные от третьей стороны. Эти данные впоследствии сохраняются в БД. Я не начинаю транзакцию БД, пока данные не вернутся из службы. Я не уверен, что понимаю то, о чем вы спрашиваете.

Mikieeee 14.01.2009 02:07

Блокировка строки - не лучшая идея. Предлагаю две альтернативы:

  1. Используйте Dictionary<int,object> в качестве типа padLocks и укажите new object(); в качестве значения.
  2. Создайте класс, который просто содержит идентификатор; это будет лучше для удобства чтения, если вы когда-нибудь захотите взглянуть на свой класс LockPad во время отладки.

LockPad класс:

class LockPad {
    public int Id { get; private set; }

    public LockPad(int id) {
        this.Id = id;
    }

    public override string ToString() {
        return "lock of " + id.ToString();
    }
}

Затем зафиксируйте этот класс.

Другие вопросы по теме