如果C#中的锁具有类似RAII的行为?

问题描述 投票:1回答:2

这有点令人困惑。在用于多线程管理的C#中,我们有互斥锁,并且有锁,此外,我还发现了这样的锁RAII实现]

        public class ReaderWriterLockSlim_ScopedLockRead : IDisposable
        {
            ReaderWriterLockSlim m_myLock;

            public ReaderWriterLockSlim_ScopedLockRead(ReaderWriterLockSlim myLock)
            {
                m_myLock = myLock;
                m_myLock.EnterReadLock();
            }

            public void Dispose()
            {
                m_myLock.ExitReadLock();
            }
        }

        public class ReaderWriterLockSlim_ScopedLockWrite : IDisposable
        {
            ReaderWriterLockSlim m_myLock;

            public ReaderWriterLockSlim_ScopedLockWrite(ReaderWriterLockSlim myLock)
            {
                m_myLock = myLock;
                m_myLock.EnterWriteLock();
            }

            public void Dispose()
            {
                m_myLock.ExitWriteLock();
            }
        }
    }

我想了解它们之间的区别,因为互斥锁是第一个多线程管理实现,您需要调用mutex.lock(),然后别忘了调用mutex.release(),通常不适合调用[C0 ],因为您可能会在执行过程中出错,所以据我所知,这里是mutex.release(),它是一种具有相同行为的RAII对象,但是如果您在执行过程中的中间出错,它将调用[ C0],一切都很好。

但是我发布的最后一个自定义实现呢?看起来与lock(obj){}相同,只是我们有mutex.release()行为不同,例如在写入状态下,可能有几个线程一对一地访问方法,而在读取状态下则只有一个线程...

我在这里吗?

c# .net
2个回答
0
投票

这根本不是。 Read Writer锁是在特定上下文中使用的实现。

  • 所有人都可以在任何时候阅读,而没有一个阻止另一个,但阻止了任何想要写的人。
  • 当时只有一次书写,没有人可以读或写

lock(obj){}完全相同,并且对C#或任何其他语言非特定。这只是ReadWriter锁的C#风格

是一个同步原语,解决了读写器问题之一。 RW锁允许并发访问只读操作,而写操作则需要排他访问。

检查read and write


0
投票

因此,对于锁定,同样重要的是,还必须释放所获得的每个锁定(无论其锁定的代码是否有任何异常)。因此,通常情况下,无论您使用什么锁,它都会看起来像这样:

wikipedia describes it here

现在Microsoft docs here for more information中的myLock.MyAcquireMethod(); try { //... } finally { myLock.MyReleaseMethod(); } 锁定机制有一个关键字可以使它更容易使用:Monitor

基本上将获取和释放包装在一个c#代码块中。

所以这个:

lock

只是写此内容的一种更方便的方法:

lock

对于其他锁(由于[C​​0]有其局限性,我们并不总是想要使用它)感到遗憾,我们没有那么方便的方法来完成整件事,并且无法解决lock(myObj) { //... } 包装器实现了Monitor.Enter(myObj); try { //... } finally { Monitor.Exit(myObj); } ,为您提供了这种Monitor ReaderWriterLockSlim_ScopedLockRead机制(IDisposable还保证无论代码运行完成还是发生异常,try都将调用finally

所以代替:

using

您现在可以执行此操作:

Dispose()

希望这能回答您的问题!

作为奖励,警告IDisposablem_myLock.EnterWriteLock(); try { //... } finally { m_myLock.ExitWriteLock(); } 类。该锁定机制在线程级别上是可重入的。意味着持有锁的线程可以多次获取(尽管它也必须多次释放),这使您可以执行以下操作:

using(new ReaderWriterLockSlim_ScopedLockRead(m_myLock))
{
    //...
}

因此,无论是直接调用还是通过Monitor调用c#(可能还需要其他内容的锁),您都可以拥有线程安全性。

[但是,现在很多人使用private readonly object _myLock = new object(); public void MyLockedMethod1() { lock(_myLock) { MyLockedMethod2(); } } public void MyLockedMethod2() { lock(_myLock) { //... } } / MyLockedMethod2,其中的方法可以在另一个线程上继续执行,如果获取该线程的线程不是释放它的线程,则该方法可能会破坏MyLockedMethod1,所以我建议您不要使用这样的东西:

async

无论如何,如果您想了解更多信息,会有很多文档。

© www.soinside.com 2019 - 2024. All rights reserved.