在下面的代码中,我有一个用于控制同步的类,名为KernalRecursiveAutoResetEvent。这有一个Lock和Leave方法,它调用AutoResetEvent WaitOne()进行锁定,调用Set()进行释放。我已经设置了一个循环,所以我可以调用一个处理共享资源的方法。在Increment方法中,我将一个int添加到共享列表中。种族分歧是因为离开被称为比洛克更快。有没有更好的方法来控制执行?抛出了InvalidOperation异常,因为检查当前线程是否等于拥有线程的条件是在通过Lock()方法设置拥有线程之前执行的。
任何提示?
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++;
}
答案 0 :(得分:1)
这不必要地复杂化。您应该在将新int添加到列表的代码周围使用lock()
。当然,你锁定的对象应该在所有线程之间是通用的。
示例:
var lockObj = new object();
for (int i = 0; i < iterations; i++)
{
// what do you mean `red i`, by the way? It's a value type.
var t = new Thread(a => Increment(ref i, lockObj));
t.Start();
}
内部Increment
:
lock (lockObj)
{
someIntList.Add(i); // or whatever. Only one thread at a time can do this!
}
当然,您的lockObj
也可能是静态的。
另外,不要开始新的主题。请改用Task
。