这个哈希集锁线程安全吗?
Is this Hashset lock threadsafe?
private static readonly object MyMethodLockobject = new object();
private static readonly HashSet<long> ActiveWorkItem = new HashSet<long>();
public async Task MyMethod(long id)
{
lock (MyMethodLockobject)
{
if (ActiveWorkItem.Contains(id))
{
throw new AnotherRequestAlreadyInProgressException();
}
ActiveWorkItem.Add(id);
}
try
{
return await DoWork(id);
}
finally
{
ActiveWorkItem.Remove(id);
}
}
ActiveWorkItem 的目的是防止对同一 ID 进行并发调用。只需要添加包含和删除。
MyMethod 是唯一具有 ActiveWorkItem 访问权限的地方。
我关心的是这一行:
finally
{
ActiveWorkItem.Remove(id);
}
或有必要改为
finally
{
lock (MyMethodLockobject)
{
ActiveWorkItem.Remove(id);
}
}
更好的选择也很受欢迎
是的,finally
块里面的HashSet
也是需要保护的
finally
{
lock (MyMethodLockobject) ActiveWorkItem.Remove(id);
}
否则,一个线程可能正在向 HashSet
添加项目,而多个线程同时从同一个 HashSet
中删除项目,可能会使对象处于损坏状态,并导致未定义的行为。
private static readonly object MyMethodLockobject = new object();
private static readonly HashSet<long> ActiveWorkItem = new HashSet<long>();
public async Task MyMethod(long id)
{
lock (MyMethodLockobject)
{
if (ActiveWorkItem.Contains(id))
{
throw new AnotherRequestAlreadyInProgressException();
}
ActiveWorkItem.Add(id);
}
try
{
return await DoWork(id);
}
finally
{
ActiveWorkItem.Remove(id);
}
}
ActiveWorkItem 的目的是防止对同一 ID 进行并发调用。只需要添加包含和删除。 MyMethod 是唯一具有 ActiveWorkItem 访问权限的地方。
我关心的是这一行:
finally
{
ActiveWorkItem.Remove(id);
}
或有必要改为
finally
{
lock (MyMethodLockobject)
{
ActiveWorkItem.Remove(id);
}
}
更好的选择也很受欢迎
是的,finally
块里面的HashSet
也是需要保护的
finally
{
lock (MyMethodLockobject) ActiveWorkItem.Remove(id);
}
否则,一个线程可能正在向 HashSet
添加项目,而多个线程同时从同一个 HashSet
中删除项目,可能会使对象处于损坏状态,并导致未定义的行为。