【问题标题】:Is it thread-safe to use the same lock object, across multiple collections?跨多个集合使用同一个锁对象是否是线程安全的?
【发布时间】:2017-10-27 09:21:42
【问题描述】:

我知道当在多个线程中工作时我必须锁定一个哈希集以使其线程安全,但我真的不明白如果你有多个哈希集怎么办?你可以使用同一个锁对象吗?还是需要一个单独的对象?

例如...我有这两种方法,它们使用相同的对象。

private void RemoveSheduledAttack(Attack attack)
{
    lock (_syncRoot)
    {
        _sheduledAttacks.Remove(attack);
    }
}

private void AddActiveAttack(Attack attack)
{
    lock (_syncRoot)
    {
        ActiveAttacks.Add(attack);
    }
}

声明:

private readonly HashSet<Attack> _sheduledAttacks;
private static object _syncRoot = new object();
public HashSet<Attack> ActiveAttacks;

【问题讨论】:

  • 是的,使用相同的锁或不同的锁是安全的。它是由你决定。只要您以这样一种方式锁定,当正在写入 HashSet 时,它就无法从其他地方读取或写入。 附带说明,如果您使用的是public HashSet,那么无论如何您都会遇到麻烦。即使您锁定_syncRoot,您班级的任何消费者都可以直接读取或更改ActiveAttacks,您无法阻止他们。
  • 如果您愿意,您可以在整个应用程序中使用单个锁对象 - 锁的粒度越小,您阻止安全并行的次数就越多(例如,如果没有方法实际更新两个集合同时,这些方法不需要共享锁,但现在可以防止同时调用这些方法)

标签: c# .net multithreading


【解决方案1】:

不完全是您问题的答案,但希望建议使用现有的并发集合实现。

HashSet&lt;T&gt; 没有并发实现,但你可以使用ConcurrentDictionary&lt;TKey, TValue&gt;,然后你的代码变得更简洁,不需要维护锁对象

private ConcurrentDictionary<Attack, bool> _sheduledAttacks;
private ConcurrentDictionary<Attack, bool> _activeAttacks;

private void RemoveSheduledAttack(Attack attack)
{
    var dummyValue = false
    _sheduledAttacks.TryRemove(attack, out dummyValue);
}

private void AddActiveAttack(Attack attack)
{
    _activeAttacks.TryAdd(attack, false);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 2015-12-21
    • 2021-12-19
    • 2014-03-29
    • 1970-01-01
    相关资源
    最近更新 更多