У меня есть несколько сущностей БД, которые загружаются в объекты БД. Один и тот же объект БД может быть загружен в несколько объектов БД. Периодически объект БД требует специальной обработки. Эта обработка должна выполняться одним потоком за раз. Блокировка здесь в порядке.
Обновлено: Важное примечание: процесс вызывает медленную веб-службу. Это то, что я пытаюсь предотвратить. Я не понимаю, как это можно сделать безопасно без замков.
Поэтому я создаю объект «замок», на который будут ссылаться объекты БД для блокировки. Объект висячего замка основан на сущности, поэтому два или более объекта БД для одной и той же сущности будут использовать один и тот же объект висячего замка. Я сохраняю эти замки в объекте словаря, используя идентификатор объекта БД в качестве ключа. Объект замка - это тоже простой строковый объект. Это правильный подход? Я думаю, я либо переусердствовал с разработкой, либо упрощаю это. Если подход правильный, как выглядит этот код? Работает, но под нагрузкой еще не тестировал.
Спасибо :)
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];
}





Что ж, вы в конечном итоге блокируете строку, что не очень хорошая идея (хотя конкатенация означает, что интернирование не должно быть большой проблемой). Более серьезная проблема заключается в следующем:
padLocks - это проблема?padlockLock; return должен быть внутри lockДля этой секунды это было бы проще:
object itemLock;
if (!padLocks.TryGetValue(uniqueID, out itemLock)) {
itemLock = new object();
padLocks.Add(uniqueID, itemLock);
}
return itemLock;
Если этот код является достаточно локальным (т.е. ваши объекты еще не экранированы), вы можете просто lock самой записи? Намного проще ...
Мне нужно изучить эту интернированность строк. Вы не единственный, кто на это указывает.
Я думаю, что вы слишком сильно разбираетесь в технике. Если вам нужно защитить только свои сущности БД (которые, как я предполагаю, представлены в вашем коде как «объект», который я заменю на «сущность»), вы можете просто использовать его в качестве блокировки. В качестве блокировки можно использовать любой ссылочный объект:
public static func(CustomObject o)
{
if (ReadyForUpdate(o))
{
lock (entity)
{
if (ReadyForUpdate(o))
{
PerformUpdate(entity);
}
}
}
}
Это интересно, но простой ответ заключается в том, что я не хочу блокировать CustomObject, готовый к обновлению, если он не зависит от другого обновляемого CustomObject. Я думаю, что я ищу своего рода диспетчера блокировок.
Если вы используете стандартную базу данных любого типа, я бы предложил полностью сбросить эти блокировки на стороне клиента в пользу транзакций и блокировок таблиц / строк.
Метод PeformUpdate вызывает веб-службу для получения данных, а затем сохраняет их в базе данных с данными веб-службы. Мне нужно предотвратить одновременные вызовы веб-службы и обновления базы данных.
Почему вы используете веб-службу для доступа к базе данных, когда знаете, что у вас будут транзакционные обновления данных?
Вызов веб-службы получает данные от третьей стороны. Эти данные впоследствии сохраняются в БД. Я не начинаю транзакцию БД, пока данные не вернутся из службы. Я не уверен, что понимаю то, о чем вы спрашиваете.
Блокировка строки - не лучшая идея. Предлагаю две альтернативы:
Dictionary<int,object> в качестве типа padLocks и укажите new object(); в качестве значения.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();
}
}
Затем зафиксируйте этот класс.
Метод PeformUpdate вызывает очень медленную веб-службу, а затем выполняет обновление БД. Это то, что мне нужно для предотвращения параллелизма.