简体   繁体   English

如何对线程安全队列进行单元测试

[英]How to unit test a thread safe queue

I need a simple data structure with these requirements: 我需要一个具有以下要求的简单数据结构:

  • it should behave like a queue, 它应该像一个队列,
  • all the enqueue operations should be atomic. 所有入队操作都应该是原子的。

I have very limited experience with multithreading, but this is what I came up to: 我对多线程的经验非常有限,但这就是我的目标:

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!");
    }
}

First question: is this code ok? 第一个问题:这段代码好吗?

Secod question: how can I unit test this class (for instance with two threads which are perfoming dequeue operation periodically on the queue with elements (1, 2, 3, 4, 5, 6) and the first thread should get only odd numbers and the second thread only the even numbers)? Secod问题:我怎样才能对这个类进行单元测试(例如,两个线程在队列中定期执行出队操作,元素为(1,2,3,4,5,6),第一个线程只能得到奇数和第二个线程只有偶数)? I tried this, but the asserts aren't executing: 我试过这个,但断言没有执行:

[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();
}

I would use chess: http://research.microsoft.com/en-us/projects/chess 我会用国际象棋: http//research.microsoft.com/en-us/projects/chess

CHESS is a tool for finding and reproducing Heisenbugs in concurrent programs. CHESS是一种在并行程序中查找和复制Heisenbugs的工具。 CHESS repeatedly runs a concurrent test ensuring that every run takes a different interleaving. CHESS重复运行并发测试,确保每次运行都采用不同的交错。 If an interleaving results in an error, CHESS can reproduce the interleaving for improved debugging. 如果交错导致错误,CHESS可以重现交错以改进调试。 CHESS is available for both managed and native programs. CHESS适用于托管和本机程序。

The problem with multithreading and unit tests is one of timing. 多线程和单元测试的问题是时间问题。 When you try to introduce multiple threads to unit tests you run the risk of non-reproducable test results, tests that pass sometimes but not other times. 当您尝试将多个线程引入单元测试时,您将面临不可重现的测试结果的风险,测试有时会通过,但有时则不会通过。

But just to explain why your asserts may not be executing, the unit test completes before the threads. 但只是为了解释为什么你的断言可能没有执行,单元测试在线程之前完成。 It needs to wait for the threads to complete rather than just kicking them off and moving on. 它需要等待线程完成而不是仅仅将它们踢掉并继续前进。 It's also feasible that the unit test framework itself is not threadsafe or capable of Asserts being called from other threads. 单元测试框架本身不是线程安全的或者能够从其他线程调用Asserts也是可行的。

Sorry it's not a solution, but I don't know of any automated testing solution for multithreaded code either. 对不起,这不是一个解决方案,但我不知道任何多线程代码的自动化测试解决方案。

See also: How should I unit test threaded code? 另请参阅: 我应该如何对线程代码进行单元测试?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM