【发布时间】:2013-05-08 20:04:50
【问题描述】:
我需要一个具有这些要求的简单数据结构:
- 它的行为应该像一个队列,
- 所有入队操作都应该是原子的。
我在多线程方面的经验非常有限,但这就是我的想法:
public class Tickets
{
private ConcurrentQueue<uint> _tickets;
public Tickets(uint from, uint to)
{
Initialize(from, to);
}
private readonly object _lock = new object();
public void Initialize(uint from, uint to)
{
lock(_lock)
{
_tickets = new ConcurrentQueue<uint>();
for (uint i = from; i <= to; i++)
{
_tickets.Enqueue(i);
}
}
}
public uint Dequeue()
{
uint number;
if (_tickets.TryDequeue(out number))
{
return number;
}
throw new ArgumentException("Ticket queue empty!");
}
}
第一个问题:这段代码可以吗?
第二个问题:我如何对这个类进行单元测试(例如,两个线程定期在队列上执行出队操作,元素为(1、2、3、4、5、6),第一个线程应该只得到奇数和第二个线程只有偶数)?我试过这个,但断言没有执行:
[Test]
public void Test()
{
var tickets = new Tickets(1, 4);
var t1 = new Thread(() =>
{
Assert.AreEqual(1, tickets.Dequeue());
Thread.Sleep(100);
Assert.AreEqual(3, tickets.Dequeue());
});
var t2 = new Thread(() =>
{
Assert.AreEqual(2, tickets.Dequeue());
Thread.Sleep(100);
Assert.AreEqual(4, tickets.Dequeue());
});
t1.Start();
t2.Start();
}
【问题讨论】:
-
第一个问题的答案:你的集合不是线程安全的,因为
Dequeue可以在Initializing 时调用。 -
需要锁定您的
Dequeue。同样,两个线程将像这样理想地交错的概念也是有缺陷的。不能保证他们会像那样轮流使用它,当然不是在您提供的代码中。 -
@weston:我是这么认为的,这就是为什么我问如何以适当的方式进行单元测试。
-
您不使用框架并发队列是否有原因? msdn.microsoft.com/en-us/library/…
-
他们以“循环”的方式从队列中取出重要还是只是为了测试目的。即在真实环境中,您是否关心线程 1 是否在线程 2 之前同时使用 1 和 2?
标签: c# .net multithreading unit-testing queue