首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在ReaderWriterLockSlim后处理ExitWriterLock

在ReaderWriterLockSlim后处理ExitWriterLock
EN

Stack Overflow用户
提问于 2022-05-13 05:32:50
回答 1查看 96关注 0票数 0

我有一个函数来清理一些对象以及ReaderWriterLockSlim。但是,我需要ReaderWriterLockSlim锁定为写入器锁,以防止另一个线程在进行清理时读取数据。

代码语言:javascript
复制
ConcurrentDictionary<string, ReaderWriterLockSlim> RwLocks = new ConcurrentDictionary<string, ReaderWriterLockSlim>();

private ReaderWriterLockSlim GetRwLock(string key)
{
    return RwLocks.GetOrAdd(key, _ => new ReaderWriterLockSlim());
}

public void CleanUp(string key)
{
    ReaderWriterLockSlim rwLock = this.GetRwLock(key);

    try 
    {
        rwLock.EnterWriterLock();
        // do some other clean up
        this.RwLocks.TryRemove(key, out _);
    }
    finally
    {
        rwLock.ExitWriterLock();
        // It is safe to do dispose here?
        // could other thread enter the read lock or writer lock here?
        // and the dispose will throw exceptions?
        // What is the best practice to do the dispose?
        rwLock.Dispose();
    }
}

我有个主意来包装ReaderWriterLockSlim。你认为它能解决这个问题还是有潜在的风险?

代码语言:javascript
复制
public class ReaderWriterLockSlimWrapper
{
    private ReaderWriterLockSlim rwLock;

    private volatile bool disposed;

    public ReaderWriterLockSlimWrapper()
    {
        rwLock = new ReaderWriterLockSlim();
        disposed = false;
    }

    private void DisposeInternal()
    {
        if (!rwLock.IsReadLockHeld && !rwLock.IsUpgradeableReadLockHeld && !rwLock.IsWriteLockHeld)
        {
            rwLock.Dispose();
        }
    }

    public void Dispose()
    {
        disposed = true;

        DisposeInternal();
    }

    public void EnterReadLock()
    {
        rwLock.EnterReadLock();
    }

    public void ExitReadLock()
    {
        rwLock.ExitReadLock();

        if (disposed)
        {
            DisposeInternal();
        }
    }

    public void EnterWriteLock()
    {
        rwLock.EnterWriteLock();
    }

    public void ExitWriteLock()
    {
        rwLock.ExitWriteLock();

        if (disposed)
        {
            DisposeInternal();
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2022-05-14 06:37:43

您还没有描述打算使用两种机制的特定场景,第一种机制使用CleanUp/GetRwLock方法,第二种机制使用ReaderWriterLockSlimWrapper类。所以我想问题是:

是我的两种安全机制,可以在所有可能的多线程场景中使用,在这些场景中,线程安全和操作原子性是必需的?

答案是否定的,你的两种机制都充满了种族条件,也不能保证原子性。在多线程场景中使用它们会导致未定义的行为,包括但不限于:

预期正确使用的策略( exceptions.

  • Violations )将强制执行
  1. 意外的策略。可以这样说,两个线程可能会同时为相同的密钥获取一个写入器锁,或者与为同一键获得读取器锁的其他线程同时获得一个写入器锁,或者两者都获得。

解释为什么你的机制是有缺陷的,这是相当复杂的。一般的解释是,每当您在多线程环境中使用模式if (x.BooleanProperty) x.Method();时,尽管BooleanPropertyMethod可能是单独的线程安全的,但您允许第二个线程抢占两个调用之间的当前线程,并使第一个检查的结果无效。

另外,请注意,ReaderWriterLockSlim不是跨进程同步原语。因此,即使您修复了您的机制,然后尝试在web应用程序中使用它们,这些策略仍然可能会被违反,因为web服务器可能会在任意时刻决定回收当前进程并启动一个新进程。在这种情况下,web应用程序可以在两个进程上同时运行,时间跨度为几秒钟甚至几分钟。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72224844

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档