【问题标题】:Is ReaderWriterLockSlim.EnterReadLock necessary for List<SomeObject>.Count?List<SomeObject>.Count 是否需要 ReaderWriterLockSlim.EnterReadLock?
【发布时间】:2021-10-26 04:28:44
【问题描述】:

someList.Count 线程在 C# 中是安全的吗?

性能对我来说非常重要,由于主程序的复杂性,我不能使用其他线程安全集合

我知道还有很多其他的情况,但只关注这个简单的问题:

someList.Count 是否需要 _lock.EnterReadLock,因为它可能是一个原子属性?

private ReaderWriterLockSlim _lock;
private List<SomeObject> _someList;

public void Add(SomeObject obj)
{
    try
    {
        _lock.EnterReadLock();
                
        if (_someList.Count < 10)
        {
            try
            {
                _lock.EnterWriteLock();

                _someList.Add(obj);
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
    }
    finally
    {
        _lock.ExitReadLock();
    }
}

【问题讨论】:

  • 99% 的情况下,您最好只使用lock 而不是ReaderWriterLockSlim。代码编写起来要简单得多,而且更难出错。如果您随后确定存在性能问题,则(并且仅在那时)切换到 ReaderWriterLockSlim
  • 告诉我们someList 的用途。你为什么需要它?为什么要加东西呢?它们何时以及为何被移除?
  • 访问Count不会破坏数据结构。但是,当然,如果您没有锁定所有它告诉您的是最近,计数是一个特定的数字。它无法让您了解列表now 的状态。这足以满足您的目的吗?
  • @Damien_The_Unbeliever 更准确的说法是使用当前实现 You will not corrupt the data structure。文档明确不承诺未来会这样。
  • 我们确实解决了主要(真正的、潜在的)问题。您不需要 any 显式锁定。您每周更新一次。使用我指给你的方法。这就是你所需要的。每周创建一个新列表。 CompareExchange 输入。完成。不需要任何其他锁定。

标签: c# multithreading list asp.net-core thread-safety


【解决方案1】:

如果您希望在读取计数之前确保任何写入操作都已完成,则需要读取锁。假设所有写操作都使用写锁。

要在读锁中输入写锁,您必须使用EnterUpgradeableReadLock 。在读锁中调用EnterWriteLock 会抛出异常。如果您应该使用写锁或可升级锁,请阅读https://stackoverflow.com/a/26578074/9271844

有关ReaderWriterLockSlim 类的更多信息,请参阅https://docs.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim?view=net-5.0

【讨论】:

  • 通过阅读stackoverflow.com/questions/21411018/…,我认为使用EnterUpgradeableReadLock的目的只是为了提高效率,而不是防止死锁
  • 但是你提到了加快速度的好方法
  • 值得强调的是,如果使用锁定,则需要对列表的所有访问使用它(不仅仅是获取Count)。
  • @mehdi 我检查了文档,你说得对,不需要防止死锁。根本不允许在读锁中获得写锁。我会将您的链接添加到答案中。
【解决方案2】:

不写_lock.EnterReadLock()也不例外,但是list.Count可能不是预期的数字,所以如果我们需要确切的list.Count,最好使用_lock.EnterReadLock()瞬间!

【讨论】:

    猜你喜欢
    • 2016-08-04
    • 1970-01-01
    • 2019-03-12
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 2014-09-28
    • 1970-01-01
    相关资源
    最近更新 更多