4

これらの要件を持つ単純なデータ構造が必要です。

  • キューのように動作する必要があります。
  • すべてのエンキュー操作はアトミックである必要があります。

マルチスレッドの経験は非常に限られていますが、これが私が思いついたものです:

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

最初の質問: このコードは大丈夫ですか?

2 番目の質問: このクラスを単体テストするにはどうすればよいですか (たとえば、要素 (1、2、3、4、5、6) を持つキューで定期的にデキュー操作を実行している 2 つのスレッドで、最初のスレッドは奇数のみを取得し、 2 番目のスレッドは偶数のみ)? 私はこれを試しましたが、アサートは実行されていません:

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

2 に答える 2

5

私ならチェスを使います: http://research.microsoft.com/en-us/projects/chess

CHESS は、並列プログラムで Heisenbugs を見つけて再現するためのツールです。CHESS は並行テストを繰り返し実行し、実行ごとに異なるインターリーブが行われるようにします。インターリーブによってエラーが発生した場合、CHESS はインターリーブを再現してデバッグを改善できます。CHESS は、マネージド プログラムとネイティブ プログラムの両方で使用できます。

于 2013-05-14T14:39:19.390 に答える
4

マルチスレッドと単体テストの問題は、タイミングの 1 つです。単体テストに複数のスレッドを導入しようとすると、再現性のないテスト結果、つまりテストに合格することもあれば合格しないこともあるというリスクがあります。

ただし、アサートが実行されない理由を説明するために、単体テストはスレッドの前に完了します。スレッドを開始して先に進むのではなく、スレッドが完了するのを待つ必要があります。単体テスト フレームワーク自体がスレッド セーフではないか、他のスレッドから Assert を呼び出すことができない可能性もあります。

申し訳ありませんが、解決策ではありませんが、マルチスレッド コードの自動テスト ソリューションも知りません。

参照:スレッド化されたコードを単体テストするにはどうすればよいですか?

于 2013-05-14T14:35:59.730 に答える