Tcq*_*qqp 5 .net c# multithreading deadlock
我在C#中尝试使用线程,结果创建了以下类.我试图避免任何竞争条件,但使用时会出现死锁.
该类使用两个不同的锁,一个用于简单操作的自旋锁,另外还有一个Monitor锁以在没有对象准备好的情况下等待.我最初使用EventWaitHandle,但发现种族条件由于WaitOne/ Set优先而不可避免.
注意,Monitor.Pulse不能先于Monitor.Wait,否则还有什么可能导致死锁?在5个线程使用TestPool容量为4 的类的情况下,死锁总是SpinLock在不规则的时刻发生.
internal class TestPool<T> where T : class
{
private int capacity;
private int unitPos;
private int waitUnitPos;
private int waitCount;
private int lockState;
private object lockObj;
private T[] units;
private Func<T> unitFactory;
public TestPool(int capacity, Func<T> unitFactory)
{
this.lockObj = new object();
this.unitFactory = unitFactory;
Init(capacity);
}
public T Fetch()
{
T unit;
Lock();
unit = (unitPos != capacity) ? units[unitPos++] : Wait();
Unlock();
return unit;
}
public void Store(T unit)
{
Lock();
if (waitCount == 0)
{
units[--unitPos] = unit;
}
else
{
Pulse(unit);
}
Unlock();
}
private T Wait()
{
waitCount++;
lock (lockObj)
{
Unlock();
Monitor.Wait(lockObj);
Lock();
return units[--waitUnitPos];
}
}
private void Pulse(T unit)
{
waitCount--;
units[waitUnitPos++] = unit;
lock (lockObj)
{
Monitor.Pulse(lockObj);
}
}
private void Lock()
{
if (Interlocked.CompareExchange(ref lockState, 1, 0) != 0)
{
SpinLock();
}
}
private void SpinLock()
{
SpinWait spinWait = new SpinWait();
do
{
spinWait.SpinOnce();
}
while (Interlocked.CompareExchange(ref lockState, 1, 0) != 0);
}
private void Unlock()
{
Interlocked.Exchange(ref lockState, 0);
}
private void Init(int capacity)
{
T[] tx = new T[capacity];
for (int i = 0; i < capacity; i++)
{
tx[i] = unitFactory.Invoke();
}
units = tx;
this.capacity = capacity;
}
}
Run Code Online (Sandbox Code Playgroud)
修复。我必须将以下代码放在Monitor锁外面。
Lock();
return units[--waitUnitPos];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |