我已经实现了一个通用的ObjectPool类,但是经历过它有时死锁(发生在Monitor.Wait(poolLock))
有人能发现错误吗?
public class ObjectPool<T> where T : new()
{
private readonly object poolLock = new object();
Stack<T> stack = null;
public ObjectPool(int count)
{
stack = new Stack<T>(count);
for (int i=0; i<count; i++)
stack.Push(new T());
}
public T Get()
{
lock (poolLock)
{
//if no more left wait for one to get Pushed
while (stack.Count < 1)
Monitor.Wait(poolLock);
return stack.Pop();
}
}
public void Put(T item)
{
lock (poolLock)
{
stack.Push(item);
//If adding first send signal
if (stack.Count == 1)
Monitor.Pulse(poolLock);
}
}
使用
try
{
service = myPool.Get();
}
finally
{
if (service != null)
myPool.Put(service);
}
答案 0 :(得分:3)
死锁可能发生在stack.Count > 0
。这意味着您有等待/脉冲问题。在Push()之后总是调用Pulse并不是一个坏主意。或者至少当Count&lt; 5左右。请记住,Wait / Pulse机制没有内存。
场景:
线程A尝试从空中获取 池,并做一个Wait()
线程B尝试 从一个空池中获取,然后做一个 等待()线程C进入池中,是否有脉冲() 线程D放回池中而不是Pulse(Count == 2)
线程A被激活并获取其项目 线程B保持等待。对复苏没什么希望。
答案 1 :(得分:0)
我现在看得更清楚了。我必须有一个读卡器锁,对吧?
public T Get()
{
lock (readerLock)
{
lock (poolLock)
{
//if no more left wait for one to get Pushed
while (stack.Count < 1)
Monitor.Wait(poolLock);
return stack.Pop();
}
}
}
答案 2 :(得分:0)
只是一个猜测,但是如何删除“stack.Count == 1”条件并始终在Put函数内部发出一个Pulse?也许两个Puts按顺序快速调用,只有一个等待线程被唤醒..
答案 3 :(得分:0)
Henk回答了你的问题。以下条件不正确:
if (stack.Count == 1)