这有点令人困惑。在用于多线程管理的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()
行为不同,例如在写入状态下,可能有几个线程一对一地访问方法,而在读取状态下则只有一个线程...
我在这里吗?
这根本不是。 Read Writer锁是在特定上下文中使用的实现。
与lock(obj){}
完全相同,并且对C#或任何其他语言非特定。这只是ReadWriter锁的C#风格
是一个同步原语,解决了读写器问题之一。 RW锁允许并发访问只读操作,而写操作则需要排他访问。
检查read and write
因此,对于锁定,同样重要的是,还必须释放所获得的每个锁定(无论其锁定的代码是否有任何异常)。因此,通常情况下,无论您使用什么锁,它都会看起来像这样:
wikipedia describes it here
现在Microsoft docs here for more information中的myLock.MyAcquireMethod();
try
{
//...
}
finally
{
myLock.MyReleaseMethod();
}
锁定机制有一个关键字可以使它更容易使用:Monitor
。
基本上将获取和释放包装在一个c#
代码块中。
所以这个:
lock
只是写此内容的一种更方便的方法:
lock
对于其他锁(由于[C0]有其局限性,我们并不总是想要使用它)感到遗憾,我们没有那么方便的方法来完成整件事,并且无法解决lock(myObj)
{
//...
}
包装器实现了Monitor.Enter(myObj);
try
{
//...
}
finally
{
Monitor.Exit(myObj);
}
,为您提供了这种Monitor
ReaderWriterLockSlim_ScopedLockRead
机制(IDisposable
还保证无论代码运行完成还是发生异常,try
都将调用finally
。
所以代替:
using
您现在可以执行此操作:
Dispose()
希望这能回答您的问题!
作为奖励,警告IDisposable
的m_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
无论如何,如果您想了解更多信息,会有很多文档。