在ExitWriterlock之后处置ReaderWriterlockslim

发布于 2025-01-28 10:14:34 字数 2086 浏览 1 评论 0原文

我有一个可以清理某些对象以及ReaderWriterlockslim的功能。但是我需要ReaderWriterlockslim作为作者锁定,以防止在我进行清理时读取数据。

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。您认为它可以解决问题或有任何潜在风险

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

I have a function to clean up some objects as well as the ReaderWriterLockSlim. But I need the ReaderWriterLockSlim to lock as writer lock to prevent the other thread read the data while I am doing the clean up.

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

I have an idea to wrap the ReaderWriterLockSlim. Do you think it could solve the problem or have any potential risk

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

违心° 2025-02-04 10:14:34

您尚未描述您打算使用两种机制的特定方案,既不是使用clearup/getrwlock方法的第一个机制,也不适用于第二种机制ReaderWriterlockslimwrapper类。所以我想问题是:

我的两种机制是否可以安全地用于所有可能的多线程场景,在该方案中,强制性操作的线程和原子能是强制性的?

答案是否定的,您的两种机制都充满了种族条件,并且无法保证原子能。在多线程方案中使用它们将导致不确定的行为,包括但不限于:

  1. 意外例外。
  2. 违反正确使用代码> 通常预计会执行。作为顺序的单词,两个线程可能会同时获得同一键的作者锁定,或者与其他线程同时获取了以相同键或两者获得读取器锁定的其他线程。

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

附带说明,请注意,ReaderWriterlockslim不是交叉过程同步原始化。因此,即使您修复了机制,然后尝试在Web应用程序中使用它们,也可能会违反策略,因为Web服务器可能会随机决定回收当前过程并启动新过程。在这种情况下,Web应用程序可能会通过在两个进程上同时运行,在一段时间内跨越几秒钟甚至几分钟。

You haven't described the specific scenario where you intend to use your two mechanisms, neither for the first one with the CleanUp/GetRwLock methods, nor for the second one with the ReaderWriterLockSlimWrapper class. So I guess the question is:

Are my two mechanisms safe to use in all possible multithreaded scenarios, where thread-safety and atomicity of operations is mandatory?

The answer is no, both of your mechanisms are riddled with race conditions, and offer no guarantees about atomicity. Using them in a multithreaded scenario would result in undefined behavior, including but not limited to:

  1. Unexpected exceptions.
  2. Violations of the policies that a correctly used ReaderWriterLockSlim is normally expected to enforce. In order words it is possible that two threads will acquire a writer lock for the same key concurrently to each other, or concurrently with others threads that have acquired a reader lock for the same key, or both.

Explaining why your mechanisms are flawed is quite involved. A general explanation is that whenever you use the pattern if (x.BooleanProperty) x.Method(); in a multithreaded environment, although the BooleanProperty and the Method might be individually thread-safe, you are allowing a second thread to preempt the current thread between the two invocations, and invalidate the result of the first check.

As a side note, be aware that the ReaderWriterLockSlim is not a cross-process synchronization primitive. So even if you fix your mechanisms and then attempt to use them in a web application, the policies might still be violated because the web server might decide at random moments to recycle the current process and start a new one. In that case the web application might by running concurrently on two processes, for a period of time that spans a few seconds or even minutes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文