0

我有一堆加载到数据库对象中的数据库实体。同一个 DB 实体可能被加载到多个 DB 对象中。数据库实体会定期需要特殊处理。该处理必须由一个线程一次执行。锁定在这里是有序的。

编辑:重要提示:该过程调用慢速网络服务。这就是我试图防止并发的原因。我不明白如何在没有锁的情况下安全地完成这项工作。

因此,我创建了一个“挂锁”对象,数据库对象将引用该对象进行锁定。挂锁对象是基于实体的,因此同一实体的两个或多个 DB 对象将使用相同的挂锁对象。我使用数据库实体的 ID 作为键将这些挂锁存储在字典对象中。挂锁对象也只是一个简单的字符串对象。这是正确的方法吗?我在想我要么过度工程化,要么简化了这个。如果方法是正确的,这段代码看起来如何?它可以工作,但我还没有在负载下测试它。

谢谢 :)

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];
}
4

4 回答 4

1

好吧,你最终锁定了一个字符串,这不是一个好主意(尽管连接意味着实习不应该是一个大问题)。更大的问题是:

  • 您似乎没有从中删除锁padLocks-这是一个问题吗?
  • padlockLock您在;之外访问字典 return应该在里面lock

对于这一秒,这会更简单:

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

如果此代码是相当本地的(即您的对象尚未转义),您可能只是lock记录本身?简单很多...

于 2009-01-13T21:59:18.817 回答
1

锁定字符串不是一个好主意。我建议两种选择:

  1. 使用 aDictionary<int,object>作为 padLocks 的类型,并将 anew object();作为值。
  2. 创建一个只保存 id 的类;如果您想在调试时查看 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();
    }
}

然后,锁定该类。

于 2009-01-13T23:41:21.107 回答
0

我认为你过度工程。如果您只需要保护您的数据库实体(我假设在您的代码中由“对象”表示,我将其更改为“实体”),您可以将其用作您的锁。任何引用对象都可以用作锁:

public static func(CustomObject o)
{
    if (ReadyForUpdate(o))
    {
        lock (entity)
        {
                if (ReadyForUpdate(o))
                {
                        PerformUpdate(entity);
                }
        }
    }
}
于 2009-01-13T22:05:00.893 回答
0

如果您使用任何类型的标准数据库,我建议完全转储这些客户端锁以支持事务和表/行锁。

于 2009-01-13T22:10:06.517 回答