我有一个.NET类,有三个方法:Get1(),Get2()和Disconnect()。 Get1和Get2可以在两个线程中同时调用,但我需要在Disconnect和其他两个方法之间保留互斥。换句话说,我不希望它通过“get”中途断开连接。
我可以使用两个锁来执行此操作,如下所示:
private object lock1 = new object();
private object lock2 = new object();
public void Get1()
{
lock(lock1)
{
// work
}
}
public void Get2()
{
lock(lock2)
{
// work
}
}
public void Disconnect()
{
lock(lock1)
{
lock(lock2)
{
// work
}
}
}
这是实现上述结果的最佳做法吗?我应该关注死锁吗?如果有两个以上可并行化的方法 - 拥有 n 锁定似乎不是一个好的解决方案。
答案 0 :(得分:0)
修改强>
我正在考虑更多关于这个问题,我知道它符合一个模式,但不记得它是什么,然后我浏览了System.Threading类并找到了它 - 这符合Reader / Writer模式,并且有一个锁定 - ReaderWriterLockSlim
这是一个使用此锁的示例类,并且具有可以在get和disconnect调用中传递的方法(或者您可以将此锁添加到您的类中并按照示例中的模式进行操作)
public class GetAndDisconnectLocker : IDisposable
{
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void ExecuteGet(Action action)
{
_lock.EnterReadLock();
try
{
action();
}
finally
{
_lock.ExitReadLock();
}
}
public T ExecuteGet<T>(Func<T> function)
{
_lock.EnterReadLock();
try
{
return function();
}
finally
{
_lock.ExitReadLock();
}
}
public void ExecuteDisconnect(Action action)
{
_lock.EnterWriteLock();
try
{
action();
}
finally
{
_lock.ExitWriteLock();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing && _lock != null)
{
_lock.Dispose();
_lock = null;
}
}
}
原始答案
在我的头顶,我可能会用ManualResetEvents处理这个问题。您可以为每种方法创建一个事件,并使用Disconnect
方法中的WaitAll确保所有Get
方法都已完成,然后再继续Disconnect
。如果您希望Get方法运行得相当短,您可能需要考虑ManualResetEventSlim
哪个应该更适合短期运行的进程。它使用旋转而不是事件句柄。
ManualResetEvent get1 = new ManualResetEvent(false);
ManualResetEvent get2 = new ManualResetEvent(false);
ManualResetEvent disc = new ManualResetEvent(false);
public void Get1()
{
disc.WaitOne();
get1.Reset();
try
{
// Do stuff
}
finally
{
get1.Set();
}
}
public void Get2()
{
disc.WaitOne();
get2.Reset();
try
{
// Do stuff
}
finally
{
get2.Set();
}
}
public void Disconnect()
{
disc.Reset();
try
{
WaitHandle.WaitAll(new [] { get1, get2 });
// Do Stuff
}
finally
{
disc.Set();
}
}