cap*_*aig 4 c# synchronization mutex
我有多个线程将数据写入公共源,并且我希望两个线程相互阻塞,当且仅当它们触及相同的数据时.
有办法专门锁定任意键会很好:
string id = GetNextId();
AquireLock(id);
try
{
DoDangerousThing();
}
finally
{
ReleaseLock(id);
}
Run Code Online (Sandbox Code Playgroud)
如果没有其他人试图锁定相同的密钥,我希望他们能够同时运行.
我可以使用一个简单的互斥体字典来实现这一点,但是我需要担心驱逐旧的,未使用的锁,如果集合变得太大,这可能会成为一个问题.
是否存在此类锁定模式的现有实现.
您可以尝试使用a ConcurrentDictionary<string, object>来创建命名对象实例.当你需要一个新的锁实例(之前没有使用过)时,你可以将它添加到字典中(添加是一个原子操作GetOrAdd),然后一旦你从字典中提取它,所有线程都可以共享同一个命名对象,根据您的数据.
例如:
// Create a global lock map for your lock instances.
public static ConcurrentDictionary<string, object> GlobalLockMap =
new ConcurrentDictionary<string, object> ();
// ...
var oLockInstance = GlobalLockMap.GetOrAdd ( "lock name", x => new object () );
if (oLockInstance == null)
{
// handle error
}
lock (oLockInstance)
{
// do work
}
Run Code Online (Sandbox Code Playgroud)
您可以使用ConcurrentDictionary<string, object>创建和重用不同的锁。如果您想从字典中删除锁,并在将来重新打开相同的命名资源,则必须始终在临界区域内检查先前获取的锁是否已被其他线程删除或更改。在离开临界区之前,请注意从字典中删除锁作为最后一步。
static ConcurrentDictionary<string, object> _lockDict =
new ConcurrentDictionary<string, object>();
// VERSION 1: single-shot method
public void UseAndCloseSpecificResource(string resourceId)
{
bool isSameLock;
object lockObj, lockObjCheck;
do
{
lock (lockObj = _lockDict.GetOrAdd(resourceId, new object()))
{
if (isSameLock = (_lockDict.TryGetValue(resourceId, out lockObjCheck) &&
object.ReferenceEquals(lockObj, lockObjCheck)))
{
try
{
// ... open, use, and close resource identified by resourceId ...
// ...
}
finally
{
// This must be the LAST statement
_lockDict.TryRemove(resourceId, out lockObjCheck);
}
}
}
}
while (!isSameLock);
}
// VERSION 2: separated "use" and "close" methods
// (can coexist with version 1)
public void UseSpecificResource(string resourceId)
{
bool isSameLock;
object lockObj, lockObjCheck;
do
{
lock (lockObj = _lockDict.GetOrAdd(resourceId, new object()))
{
if (isSameLock = (_lockDict.TryGetValue(resourceId, out lockObjCheck) &&
object.ReferenceEquals(lockObj, lockObjCheck)))
{
// ... open and use (or reuse) resource identified by resourceId ...
}
}
}
while (!isSameLock);
}
public bool TryCloseSpecificResource(string resourceId)
{
bool result = false;
object lockObj, lockObjCheck;
if (_lockDict.TryGetValue(resourceId, out lockObj))
{
lock (lockObj)
{
if (result = (_lockDict.TryGetValue(resourceId, out lockObjCheck) &&
object.ReferenceEquals(lockObj, lockObjCheck)))
{
try
{
// ... close resource identified by resourceId ...
// ...
}
finally
{
// This must be the LAST statement
_lockDict.TryRemove(resourceId, out lockObjCheck);
}
}
}
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2178 次 |
| 最近记录: |