【发布时间】:2010-09-13 00:11:20
【问题描述】:
应用程序有一个辅助线程。这个线程并不意味着一直运行,但主进程可以经常调用它。
所以,我的问题是,就 CPU 性能而言,什么更优化:在不使用线程时挂起线程或保持线程处于活动状态并使用 WaitForSingleObject 函数等待来自主进程的信号?
【问题讨论】:
标签: windows multithreading delphi winapi
应用程序有一个辅助线程。这个线程并不意味着一直运行,但主进程可以经常调用它。
所以,我的问题是,就 CPU 性能而言,什么更优化:在不使用线程时挂起线程或保持线程处于活动状态并使用 WaitForSingleObject 函数等待来自主进程的信号?
【问题讨论】:
标签: windows multithreading delphi winapi
就使用的 CPU 资源而言,两种解决方案是相同的 - 挂起的线程和在 WaitForSingleObject 中等待未发出信号的对象的线程都完全没有 CPU 周期。
也就是说,WaitForSingleObject 几乎总是一个首选的解决方案,因为使用它的代码会更加“自然”——更容易阅读,也更容易做出正确的选择。挂起/恢复线程可能很危险,因为您需要非常小心以确保您知道您正在将一个线程挂起,并且挂起它不会造成任何伤害(想象挂起一个当前持有互斥锁的线程)。
【讨论】:
我假设 Andrei 不使用 Delphi 编写 .NET,因此 Suspend 不会转换为 System.Threading.Thread.Suspend 而是转换为 SuspendThread Win32 API。
我强烈建议不要这样做。如果您在任意时刻暂停线程,那么您不知道会发生什么(例如,您可能会在某些共享资源被阻塞的状态下暂停线程)。但是,如果您已经知道线程处于可挂起状态,则只需使用 WaitForSingleObject(或任何其他 WaitFor 调用) - 它与挂起线程同样有效,即线程将使用零 CPU 时间,直到它被唤醒。
【讨论】:
“暂停”是什么意思? WaitForSingleObject 将暂停线程,即它不会消耗任何 CPU,直到信号到达。
【讨论】:
如果它是一个工作线程,它有外部分配给它的工作单元,它肯定应该使用信号对象,因为这将确保它不会不必要地使用 CPU。
如果它也有自己的工作要做,那就另当别论了。我不会从另一个线程挂起线程(如果有两个线程向它交付工作会发生什么?) - 我的基本规则是线程应该根据其他线程的建议来控制自己的生命周期。这会将线程本身的所有控制本地化。
【讨论】:
查看 Delphi 中关于多线程的优秀教程: Multi Threading Tutorial
【讨论】:
另一个选项是 Delphi 2009 中引入的 TMonitor,它具有 Wait、Pulse 和 PulseAll 等功能,可以在线程无事可做时保持线程处于非活动状态,并在它们继续工作时立即通知它们。它是在 Java 中的对象锁之后松散地建模的。就像那里一样,Delphi 对象现在有一个“锁”字段,可用于线程同步。
可以在http://delphihaven.wordpress.com/2011/05/04/using-tmonitor-1/找到一个给出线程队列类示例的博客
不幸的是,TMonitor 实现中有一个错误,似乎在 XE2 中已修复
【讨论】: