如何解决如何基于密钥同步代码块?
| 我有一个通过WCF MSMQ传输公开的服务。 该服务所做的部分工作是根据键(源,item_id)查找项。 如果找到一个,它将检索数据库标识符,并使用该标识符来更新记录。 如果找不到,则会插入新记录。 我注意到有两个项目可能同时进入,都看到数据库中不存在一个项目,并且它们都尝试插入,但是其中一个失败并出现约束错误。 我想限制对数据库查找的访问以及基于某个键(源,item_id)的以下代码的访问权限,以便一次只有一个线程可以为该特定键完成工作。 我已经编写了一些代码来实现此目的,但是我想就是否可行或是否有更好的方法获得一些反馈。 使用LockManager
类的代码:
public class ItemService
{
private static LockManager lockManager = new LockManager();
public void AddItem(Item item){
var itemKey = item.source + \":\" + item.ItemId;
lockManager.Work(itemKey,delegate(){ do stuff });
}
}
LockManager
课:
public class LockManager
{
private readonly IDictionary<string,LockObject> _lockTable =
new Dictionary<string,LockObject>();
public void Work(string key,Action work)
{
var lockObject = BorrowLockObject(key);
try
{
lock (lockObject)
{
work();
}
}
finally
{
ReturnLockObject(lockObject);
}
}
private LockObject BorrowLockObject(string key)
{
lock (_lockTable)
{
LockObject lockObject = null;
if (_lockTable.ContainsKey(key))
{
lockObject = _lockTable[key];
}
else
{
lockObject = new LockObject(key);
_lockTable[key] = lockObject;
}
lockObject.open();
return lockObject;
}
}
private void ReturnLockObject(LockObject lockObject)
{
lock (_lockTable)
{
if (lockObject.Close())
{
_lockTable.Remove(lockObject.GetKey());
}
}
}
}
LockObject
班:
public class LockObject
{
private readonly string _key;
private int _count;
public LockObject(string key)
{
_key = key;
_count = 0;
}
public string GetKey()
{
return _key;
}
public void open()
{
lock(this)
{
_count++;
}
}
/// <summary>
/// Closes this lock object.
/// </summary>
/// <returns>True if this Lock Object is no longer in use.</returns>
public bool Close()
{
lock(this)
{
_count--;
return _count == 0;
}
}
}
解决方法
在一个单独的线程上将
Pair<Key,Action>
和WorkManager
的同步集合作为队列(从后到前)进行工作将大大简化此过程。您可以弹出并丢弃包含相同密钥的所有对,然后再对其进行处理并完成对它的操作(在执行此操作时将其锁定)。
>
客户添加
锁收集
加
解锁收藏
>
反线程迭代:
锁收集
获取工作项(集合中的最后一个)
从收藏中删除
解锁收藏
工作...(与此同时,客户会添加更多,甚至可能重复)
锁收集
使用相同的键删除所有项目(并正确处理)
解锁收藏
顺便说一句:public delegate void Worker();
在Action
中有一个快捷方式。
,这可行。 2件事:字典永远不会释放键和值;如果要同时获取两个锁,请确保始终以相同的顺序访问它们(避免对钥匙进行排序),从而避免死锁。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。