2010-10-06 63 views
0

请看下面的测试片段:如何确保这个多线程问题的不确定结果?

 // act 
     AutoResetEvent workDoneEvent = new AutoResetEvent(false); 
     ThreadPool.QueueUserWorkItem(delegate 
             { 
              ProcessAndSignal(processor, workDoneEvent); 
             }, null); 

     // let worker thread have a go 
     workDoneEvent.WaitOne(); 
     blockingFetcher.WaitForNextMessage = false; 

     // assert 
     Assert.That(processor.StopCause, Is.Null); 
    } 

    private static void ProcessAndSignal(MessageProcessor processor, AutoResetEvent workDoneEvent) 
    { 
     workDoneEvent.Set(); 
     // this invocation will block until the WaitForNextMessageFlag is set 
     processor.ProcessMessages(); 
    } 

理想的方案:

  1. ProcessAndSignalMethod排队线程池,但没有开始执行。
  2. 主线程块(autoResetEvent.WaitOne())
  3. 辅助线程开始执行“ProcessAndSignal”方法
  4. 工作线程有足够的时间到信号标志并启动ProcessMessages方法的执行
  5. 主线程重新生成并设置将导致ProcessAndSignal方法优雅地完成的属性

可以发生以下情况吗?

1)ProcessAndSignal()将开始执行主线程设置的AutoResetEvent到了WaitOne(),这将导致死锁(在processor.ProcessMessages(前)将进入不定式环路)

回答

1

是的,情况可能会发生。是的,如果你没有将bool变量声明为volatile,它会死锁。只是不要使用布尔,使用像你这样的事件。

该逻辑看起来很奇怪,它闻起来像你正试图让主线程等待处理完成。 workDoneEvent实际上并不表示工作已完成。现在主线程会在工作完成之前检查声明,这是不行的。如果意图是表示工作完成,那么在方法结束时,ProcessAndSignal应该是调用Set()的那个。主线程应该调用WaitOne()。

如果这完全准确,那么你只是不应该使用QUWI,只需直接调用ProcessAndSignal而不使用线程。 Far效率更高,线程问题的可能性为零。