2009-03-19 24 views
0

私はスレッドのコードが含まれているときのNUnitが適切に機能していないことを考える:Nunitでスレッディングが正しく機能していませんか?

ここではサンプルコードがあります:

public class multiply 
{ 
    public Thread myThread; 
    public int Counter 
    { 
     get; 
     private set; 
    } 
    public string name 
    { 
     get; 
     private set; 
    } 
    private Object thisLock = new Object(); 
    public void RunConsolePrint() 
    { 
     //lock(thisLock) 
     //{ 
     Console.WriteLine("Now thread " + name + " has started"); 
     for (int i = 1; i<= Counter; i++) 
     { 
      Console.WriteLine(name + ": count has reached " + i+ ": total count is "+Counter); 
     } 
     Console.WriteLine("Thread " + name + " has finished"); 
     //} 
    } 
    public multiply(string pname, int pCounter) 
    { 
     name = pname; 
     Counter = pCounter; 
     myThread = new Thread(new ThreadStart(RunConsolePrint)); 
    } 
} 

そしてここでは、テストコードは次のとおりです。

[Test] 
public void Main() 
{ 
    counter=100; 

    multiply m2=new multiply("Second", counter); 
    multiply m1 = new multiply("First", counter); 
    m1.myThread.Start(); 
    m2.myThread.Start(); 

} 

、出力がありますm1m2の連続実行であり、これは、m1のループがであり、がより前に実行されることを意味します、少なくともそれは私のテストが示すものです。私はテストを数回実行し、私はいつもこれを取得します。

これはバグですか?または期待される行動ですか?

上記のコードをコンソールプログラムにコピーして実行すると、スレッディング効果がはっきりとわかります。

私はTestDriven.netランナーを使用してテストを行っています。

答えて

0

m1またはm2が最初に実行を開始するかどうかは、非決定的です。カウンタが十分速く実行されていれば、他の開始前にそれらのうちの1つが終了するのを見て驚くことはありません。数を非常に大きなもの(たとえば100万)に変更してください。別のスレッドが並行して実行されているのが分かります。

結果は可能です - どのような結果が表示され、バグがあると表示されますか?

+0

私は上記のテストを数回実行し、一貫した結果を得ました.m1は常にm2の前に最初に実行されます – Graviton

+2

これはバグがあるわけではありません。それはちょうどスケジューリングの奇抜なことかもしれません。タスクを長くするようにしてください。 –

2

2つ以上のスレッドの正確なインターリーブは実際には予測できません。

あなたの例にはいくつか考慮すべき要素があります。まず、各スレッドは、(潜在的に)別のスレッドに切り替えられる前に、その量子に対して実行されます。コード内の特別な場所でスレッドスイッチが実行されることは期待できません。私。あるスレッドがもう一方のスレッドを開始する前に終了することがあります(特に、あなたのケースではタスクが比較的短いためです)。

第2に、コンソールに書き込みを行っているので、スレッドはそのアクセスで同期します。これはインターリーブにも影響します。

結果は、マシン上で使用可能なコアの数(コード実行時のマシンの一般的な負荷)によっても異なります。

要するに、2つのスレッドの実行方法を予測することはできません。

関連する問題