2011-05-01 95 views
3

假如我有线程句柄或线程ID,是否有办法强制C++中的上下文切换到特定的线程?在Windows中强制上下文切换

+2

如果应用程序可能强制某个线程执行,那最终意味着优先级较高的进程或线程将会饿死,从而渲染任何类型的进程优先级或调度程序公平算法。另外,如果你强迫运行的线程没有准备好运行呢?如果它在阅读时被阻塞,并且醒来,它会假定有东西需要阅读。 – 2011-05-01 12:55:47

+0

问题背后的动机是什么? – 2011-05-01 13:00:06

+0

我需要非运行线程来控制关键部分。 :) – Idov 2011-05-01 13:17:16

回答

4

不,您将无法通过强制操作系统运行您想要的线程。您可以使用yield强制上下文切换,但...

yield在Win32 API中的功能是SwitchToThread。如果没有其他线程可用于运行,则将返回值ZERO,并且当前线程仍将继续运行。

+0

其实这是不正确的。 SwitchToThread不保证上下文切换。如果没有线程有资格在此处理器上运行,则此线程将继续。 – 2011-05-01 12:58:22

+0

但它可以是任何运行该处理器的线程,不仅仅是在我的进程中,对吧? – Idov 2011-05-01 13:18:34

+0

@Idov:对。它可以是任何线程运行,而不仅仅是你的过程。这是一个操作系统限制。 OS完全控制进程/线程调度。 – 2011-05-01 14:34:34

2

强制某个特定线程运行的唯一方法是使用进程/线程关联,但我无法想象这是一个合理的解决方案。

强制上下文切换的唯一方法是使用关联强制将线程放到不同的处理器上。

换句话说,你所要做的并不是真正可行的。

调用SwitchToThread()将导致上下文切换,如果有另一个线程准备好运行并且有资格在此处理器上运行。

如果调用SwitchToThread功能 导致操作系统来执行 切换到另一个线程中, 返回值为非零值:文档如下规定它。

如果有准备 执行没有其他线程,操作系统不 切换执行到另一个线程, 和返回值是零。

4

你只能鼓励Windows线程调度程序选择某个线程,你不能强制它。您首先通过在同步对象上创建线程块并发信号通知它。中学通过提高优先次序。

支持显式上下文切换,您必须使用光纤。查看SwitchToFiber()。一根纤维不是一丝不苟,它类似于一种古老的共生体。纤维的鼎盛时期已经来临,它们不再与线索竞争。他们有非常糟糕的cpu缓存位置,不能利用多个内核。

1

您可以临时碰撞另一个线程的优先级,同时调用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); 
+0

你在这里陈述的是不正确的。从'Sleep()'的文档中:值为零将导致线程将其时间片的其余部分放弃到任何其他准备运行的线程。如果没有其他线程准备好运行,则该函数立即返回,并且线程继续执行。 – 2011-05-01 14:23:50

+0

归结到同样的事情吧? – 2011-05-01 14:29:31

+0

不,它不。如果没有另一个线程准备运行,则“Sleep(0)”实际上是空操作。 – 2011-05-01 14:33:58

1

我会检查出适用于Windows的书并发编程。调度程序似乎做了一些值得注意的事情。

睡眠(0)只产生更高优先级的线程(或可能有其他优先级相同的线程)。这意味着您无法修复只有休眠(0)的优先级反转情况,其中较低优先级的线程需要运行。您必须使用SwitchToThread,睡眠时间非零,或者完全阻止某些内核手柄。

1

您可以创建两个同步对象(例如两个events)并使用API​​ SignalObjectAndWait

如果hObjectToWaitOn是无信号和您的其他线程正在等待的hObjectToSignal,操作系统可以理论上这个API内执行快速上下文切换,时间片结束之前。

如果您希望当前线程自动恢复,只需通知dwMilliseconds上的一个小值(如50或100)即可。