我需要一个具有这些要求的简单数据结构:
我对多线程的经验非常有限,但这就是我的目标:
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!");
}
}
第一个问题:这段代码好吗?
Secod问题:我怎样才能对这个类进行单元测试(例如,两个线程在队列中定期执行出队操作,元素为(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();
}
答案 0 :(得分:5)
我会使用国际象棋:http://research.microsoft.com/en-us/projects/chess
CHESS是一种在并发程序中查找和复制Heisenbugs的工具。 CHESS重复运行并发测试,确保每次运行都采用不同的交错。如果交错导致错误,CHESS可以重现交错以改进调试。 CHESS适用于托管和本机程序。
答案 1 :(得分:4)
多线程和单元测试的问题是时间问题。当您尝试将多个线程引入单元测试时,您将面临不可重现的测试结果的风险,这些测试有时会通过但不会通过其他时间。
但是为了解释为什么你的断言可能没有执行,单元测试在线程之前完成。它需要等待线程完成而不是仅仅将它们踢掉并继续前进。单元测试框架本身不是线程安全的,或者能够从其他线程调用Asserts也是可行的。
很抱歉,这不是解决方案,但我不知道任何针对多线程代码的自动化测试解决方案。