2011-05-01 86 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)即可。