在下面的代码中,我有一个用于控制同步的类KernalRecursiveAutoResetEvent。这有一个Lock和Leave方法,它调用AutoResetEvent的WaitOne()进行锁定,Set()进行释放。我设置了一个循环,所以我可以调用一个处理共享资源的方法。在方法Increment中,我将一个int添加到共享列表中。因为离开被称为快于锁定,因此比赛分子正在缩小。有没有更好的方法来控制执行?因为检查当前线程是否等于拥有线程的条件是在通过Lock()方法设置拥有线程之前执行的,所以引发InvalidOperation异常。在递归autoresertevent上解决竞态条件
任何提示?
class KernalRecursiveAutoResetEvent : IDisposable
{
private AutoResetEvent m_lock = new AutoResetEvent(false);
private int m_owningThreadId = 0;
private int m_recusionCount = 0;
public void Lock()
{
int currentThreadId = Thread.CurrentThread.ManagedThreadId;
if (m_owningThreadId == currentThreadId)
{
m_recusionCount++;
return;
}
m_lock.WaitOne();
m_owningThreadId = currentThreadId;
m_recusionCount = 1;
}
public void Leave()
{
if (m_owningThreadId != Thread.CurrentThread.ManagedThreadId)
throw new InvalidOperationException();
if (--m_recusionCount == 0)
{
m_owningThreadId = 0;
m_lock.Set();
}
}
public void Dispose()
{
m_lock.Close();
}
}
using (var rare = new KernalRecursiveAutoResetEvent())
{
for (int i = 0; i < iterations; i++)
{
var t = new Thread(a => Increment(ref i, rare));
t.Start();
rare.Lock();
}
}
private static void Increment(ref int i, object _lock)
{
Increment(ref i);
if (_lock is KernalRecursiveAutoResetEvent)
{
var m_lock = _lock as KernalRecursiveAutoResetEvent;
m_lock.Leave();
}
else if (_lock is KernalModeMutexSimpleWaitLock)
{
var m_lock = _lock as KernalModeMutexSimpleWaitLock;
m_lock.Leave();
}
else if (_lock is KernalModeSemaphoreSimpleWaitLock)
{
var m_lock = _lock as KernalModeSemaphoreSimpleWaitLock;
m_lock.Leave();
}
else if (_lock is KernalModeSimpleWaitLock)
{
var m_lock = _lock as KernalModeSimpleWaitLock;
m_lock.Leave();
}
}
private static void Increment(ref int i)
{
i++;
}
“离开被称为快于锁定” - 所以你为什么不张贴调用“离开”的代码?你可以用更传统的东西来替换你的同步原语(即'Monitor',它具有所描述的确切功能),但是如果你的代码在'Enter'之前调用'Exit',你的问题仍然会存在。 –
调用离开的代码很简单,它会增加我并调用rare.Leave()(它潜在地调用AutoResetEvent.Set()。 问题不在于了解Monitor.Enter或Exit/TryExit它是了解竞争条件和控制这个.FLC静态Monitor.Enter和Leave/TryLeave等有一些基本问题,这不是理解为什么它没有锁定的问题,它不是因为控制竞态条件失败而被锁定的。如何/为什么离开之前调用锁 –