我有一个C#应用程序。有一个Stack集合使用。
现在,这个集合正在从许多线程访问,所以我需要使它成为线程安全。
所以,我正在考虑使用ConcurrentStack Collection。
现在这使用TryPeek,TryPop,TryPush,它返回一个True / False标志来表示成功与否。
此标志是否识别对象是否存在于集合中,还是因为它可能会失败,因为另一个Thread同时访问该集合并且我需要重新尝试该操作?
以下是ConcurrentStack.TryPop<T>()
的源代码(由ILSpy反编译):
public bool TryPop(out T result)
{
ConcurrentStack<T>.Node head = this.m_head;
if (head == null)
{
result = default(T);
return false;
}
if (Interlocked.CompareExchange<ConcurrentStack<T>.Node>(ref this.m_head, head.m_next, head) == head)
{
result = head.m_value;
return true;
}
return this.TryPopCore(out result);
}
当无法移除/返回项目时,或者当false
返回TryPopCore
时,此方法返回false
。所以这就是:
private bool TryPopCore(out T result)
{
ConcurrentStack<T>.Node node;
if (this.TryPopCore(1, out node) == 1)
{
result = node.m_value;
return true;
}
result = default(T);
return false;
}
因此,返回TryPopCore(int, out ConcurrentStack<T>.Node)
是否成功:
private int TryPopCore(int count, out ConcurrentStack<T>.Node poppedHead)
{
SpinWait spinWait = default(SpinWait);
int num = 1;
Random random = new Random(Environment.TickCount & 2147483647);
ConcurrentStack<T>.Node head;
int num2;
while (true)
{
head = this.m_head;
if (head == null)
{
break;
}
ConcurrentStack<T>.Node node = head;
num2 = 1;
while (num2 < count && node.m_next != null)
{
node = node.m_next;
num2++;
}
if (Interlocked.CompareExchange<ConcurrentStack<T>.Node>(ref this.m_head, node.m_next, head) == head)
{
goto Block_5;
}
for (int i = 0; i < num; i++)
{
spinWait.SpinOnce();
}
num = (spinWait.NextSpinWillYield ? random.Next(1, 8) : (num * 2));
}
if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
{
CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spinWait.Count);
}
poppedHead = null;
return 0;
Block_5:
if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
{
CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spinWait.Count);
}
poppedHead = head;
return num2;
}
如您所见,如果无法删除项目然后将其返回,则返回false。这最后一个函数有很多,反编译的代码并不是最干净的,但它似乎符合文档所述的内容。