【发布时间】:2019-01-18 22:03:43
【问题描述】:
我发现了一个实现线程安全队列的旧代码。 我尝试使用 ConcurrentQueue 创建一个新的实现
旧代码
public class BoundedQueue<T> where T : class
{
private readonly Queue<T> _fixedSizeBuffer;
private object _bufferLock;
private int _limit;
public BoundedQueue(int limit)
{
_fixedSizeBuffer = new Queue<T>();
_limit = limit;
_bufferLock = new object();
for (int i = 0; i < _limit; i++)
{
_fixedSizeBuffer.Enqueue(null);
}
}
public void AddElementToBuffer(T element)
{
lock (_bufferLock)
{
_fixedSizeBuffer.Enqueue(element);
while (_fixedSizeBuffer.Count > _limit)
{
_fixedSizeBuffer.Dequeue();
}
}
}
public T GetElementAt(int index)
{
T element;
lock (_bufferLock)
{
element = _fixedSizeBuffer.ElementAt(_limit - index - 1);
}
return element;
}
}
我的新代码
public class FixedSizeConcurrentQueue<T> where T : class
{
private readonly ConcurrentQueue<T> _fixedSizeBuffer;
private int _maxSize;
public FixedSizeConcurrentQueue(int maxSize)
{
_maxSize = maxSize;
for (int i = 0; i < _maxSize; i++)
{
_fixedSizeBuffer.Enqueue(null);
}
}
public void AddElementToBuffer(T element)
{
_fixedSizeBuffer.Enqueue(element);
while (_fixedSizeBuffer.Count > _maxSize)
{
T item;
_fixedSizeBuffer.TryDequeue(out item);
}
}
public T GetElementAt(int index)
{
var element = _fixedSizeBuffer.ElementAt(_maxSize - index - 1);
return element;
}
}
我的问题是关于ElementAt() 函数,或者我应该更好地将其称为TryGetElement()。
在旧代码中,代码使用锁来同步不同的线程。
但是在新代码中我删除了它,因为我知道在并发收集时使用锁是一种不好的做法。
因此,如果由于队列为空而找不到索引,例如,我会遇到异常。
那么我应该用 try catch 包装它吗?
请解释一下你会怎么做。
【问题讨论】:
标签: c# concurrency queue thread-safety