【发布时间】:2012-07-31 21:03:56
【问题描述】:
我有一个多线程程序,我在一个线程(线程 A)中无条件地休眠无限时间。当另一个线程(线程 B)中发生事件时,它通过信号唤醒线程 A。现在我知道有多种方法可以做到这一点。 当我的程序在 Windows 环境中运行时,我在 Thread-A 中使用 WaitForSingleObject,在 Thread-B 中使用 SetEvent。它工作没有任何问题。 我还可以使用基于文件描述符的模型进行轮询、选择。有不止一种方法可以做到这一点。 但是,我正在尝试找到最有效的方法。每当 Thread-B 发出信号时,我想尽快唤醒 Thread-A。你认为什么是最好的选择。 我可以探索基于驱动程序的选项。
谢谢
【问题讨论】:
-
用事件或信号量发出信号是否不够有效?线程 A 通常应该立即准备好,并从其先前等待信号的状态提升优先级。如果没有可用的核心,如果它们的基本优先级相同,它可能会抢占信号器。你有实际问题吗?我看不出司机会如何帮助任何人。
-
我可能没有问题。但我的理解是,每种机制的工作方式都大不相同。例如。如果我使用一个事件,那么我请求内核安排一个事件。如果我使用 poll-select 然后我写入一个系统理解的文件,然后唤醒我的睡眠线程。因此,两者都有不同的延迟。从线程-B,我可以从线程-A 执行 IOCTL,然后向线程-A 发出信号。所以,我想知道是否有任何特定的方法比其他方法快得多。
-
您为什么不尝试对各种方法进行基准测试?由于您的性能计数器对所有线程和进程都是通用的,因此创建一个内存区域,线程 B 可以在其中标记其信号时间,线程 A 可以标记其唤醒时间(使用
QueryPerformanceCounter)。对数千次重复执行此操作并平均延迟。这可能很疯狂,但您也可以尝试在线程 A 中等待一个 volatile 标志,然后让线程 B 设置该标志并立即让自己进入睡眠状态。 -
我在同一个问题上研究了一段时间。结果:事件!基准测试将显示从设置事件到等待功能唤醒的时间不到 2 微秒。但是:优先级设置、处理器亲和性和整个系统负载都会影响结果。
-
@Arno - 是的。如果两个线程都绑定到同一个内核,操作系统不必执行任何内核间通信来使线程 A 在另一个内核上运行 - 它可以直接抢占线程 B。当然,这确实意味着 B 被留下不执行 - 如果不调整亲和力,则可以避免这种情况,因此可能会损害整体性能:(
标签: c windows multithreading