【问题标题】:Is this Hashset lock threadsafe?这个 Hashset 锁是线程安全的吗?
【发布时间】:2020-12-13 16:04:48
【问题描述】:

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);
            }
    }

更好的选择也值得赞赏

【问题讨论】:

  • 不,它不是线程安全的。您需要在锁中对 Hashset 进行所有操作。
  • ConcurrentDictionary 会比这种锁更好(更快+更容易)。要使用 HashSet 实现 it 属性,请使用 ReaderWriterLock 的某些实现来与集合交互的所有点,而不仅仅是此方法。

标签: c# concurrency locking hashset


【解决方案1】:

是的,也有必要保护finally块内的HashSet

finally
{
    lock (MyMethodLockobject) ActiveWorkItem.Remove(id);
}

否则,一个线程可能正在向HashSet 添加项目,而多个线程同时从同一个HashSet 中删除项目,可能会使对象进入损坏状态,并导致未定义的行为。

【讨论】:

    猜你喜欢
    • 2012-02-14
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    相关资源
    最近更新 更多