C#并发,锁定和字典对象

我有一堆数据库实体加载到数据库对象中。 可以将相同的DB实体加载到多个DB对象中。 DB实体需要定期进行特殊处理。 此处理必须一次由一个线程执行。 在这里按顺序锁定。

编辑:重要说明:该过程调用慢速Web服务。 这就是我试图阻止并发的原因。 我不知道如何安全地完成没有锁。

所以我创建了一个“挂锁”对象,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 padLocks = new Dictionary(); private static object LookupPadLockByID(int uniqueID) { lock (padlockLock) { if (!padLocks.ContainsKey(uniqueID)) { padLocks.Add(uniqueID, uniqueID + " is locked"); } } return padLocks[uniqueID]; } 

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

  • 你似乎没有从padLocks删除锁 – 这是一个问题吗?
  • 你访问padlockLock之外的padlockLock ; return应该在lock

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

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

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

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

  1. 使用Dictionary作为padLocks的类型,并添加一个new object(); 作为价值。
  2. 创建一个只包含id的类; 如果您想在调试时查看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(); } } 

然后,锁定该类。

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

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

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