假设我有线程句柄或线程 ID,有没有办法强制 C++ 中的上下文切换到特定线程?
6 回答
不,您将无法强制操作系统运行您想要的线程。您可以使用yield
强制上下文切换...
yield
在 Win32 API 中是函数SwitchToThread
。如果没有其他线程可用于运行,则将返回零值,并且当前线程将继续运行。
您只能鼓励 Windows 线程调度程序选择某个线程,不能强制。您首先通过在同步对象上使线程阻塞并发出信号来做到这一点。次要通过提高其优先级。
支持显式上下文切换,您必须使用纤程。查看 SwitchToFiber()。一根纤维远不是一根线,它类似于旧的协程。纤维的鼎盛时期已经过去,它们不再与线程竞争。它们具有非常糟糕的 cpu 缓存位置,并且无法利用多个内核。
强制特定线程运行的唯一方法是使用进程/线程亲和性,但我无法想象曾经有过这样一个合理解决方案的问题。
强制上下文切换的唯一方法是使用亲和力将线程强制到不同的处理器上。
换句话说,您尝试做的事情实际上并不可行。
如果有另一个线程准备好运行并且有资格在此处理器上运行,则调用SwitchToThread()
将导致上下文切换。文档说明如下:
如果调用 SwitchToThread 函数导致操作系统将执行切换到另一个线程,则返回值非零。
如果没有其他线程准备好执行,操作系统不会切换到另一个线程执行,返回值为零。
我会查看《Windows 的并发编程》一书。调度器似乎做了一些值得注意的事情。
Sleep(0) 只让给更高优先级的线程(或可能其他具有相同优先级的线程)。这意味着您不能仅使用 Sleep(0) 来修复优先级反转情况,其他较低优先级的线程需要运行。您必须使用 SwitchToThread、休眠非零持续时间或在某些内核 HANDLE 上完全阻塞。
您可以创建两个同步对象(例如两个事件)并使用 API SignalObjectAndWait。
如果hObjectToWaitOn
没有信号并且您的其他线程正在等待hObjectToSignal
,则操作系统理论上可以在时间片结束之前在此 API 内执行快速上下文切换。
如果您希望当前线程自动恢复,只需在dwMilliseconds
.
Sleep(0)
您可以在循环调用时临时提高另一个线程的优先级:这会将控制权传递给其他线程。假设另一个线程增加了一个lock
变量,你需要等到它再次变为零:
// Wait until other thread releases lock
SetThreadPriority(otherThread, THREAD_PRIORITY_HIGHER);
while (InterlockedRead(&lock) != 0)
Sleep(0);
SetThreadPriority(otherThread, THREAD_PRIORITY_NORMAL);